diff --git a/drivers/chibios/i2cslave/I2Cv1/driver.mk b/drivers/chibios/i2cslave/I2Cv1/driver.mk
deleted file mode 100644
index f8cca018e9..0000000000
--- a/drivers/chibios/i2cslave/I2Cv1/driver.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-ifeq ($(USE_HAL_I2C_FALLBACK),yes)
- # Fallback SW driver.
- ifeq ($(USE_SMART_BUILD),yes)
- ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
- PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
- endif
- else
- PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
- endif
- PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C
-else
- # Default HW driver.
- ifeq ($(USE_SMART_BUILD),yes)
- ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
- PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
- endif
- else
- PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
- endif
- PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1
-endif
diff --git a/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c b/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c
deleted file mode 100644
index e62e6db1f3..0000000000
--- a/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c
+++ /dev/null
@@ -1,1745 +0,0 @@
-/*
- ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-/*
- Concepts and parts of this file have been contributed by Uladzimir Pylinsky
- aka barthess.
-
- I2C Slave mode support added by Brent Roman (brent@mbari.org)
- Ported to ChibiOs V3 by steved
- Latest updates from original code applied 18.12.15
-
- Note that all I2C registers are 16-bit (not 32-bit, as on the later devices in the series)
- */
-
-/**
- * @file STM32/I2Cv1/i2c_lld.c
- * @brief STM32 I2C subsystem low level driver source.
- *
- * @addtogroup I2C
- * @{
- */
-
-#include "hal.h"
-
-#if HAL_USE_I2C || defined(__DOXYGEN__)
-
-// Some master code has been brought in line with V3 - set next define to zero to stick with original code
-#define USE_OLD_MASTER_STARTUP 0
-
-/*===========================================================================*/
-/* Driver local definitions. */
-/*===========================================================================*/
-
-#define I2C1_RX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \
- STM32_I2C1_RX_DMA_CHN)
-
-#define I2C1_TX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \
- STM32_I2C1_TX_DMA_CHN)
-
-#define I2C2_RX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \
- STM32_I2C2_RX_DMA_CHN)
-
-#define I2C2_TX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \
- STM32_I2C2_TX_DMA_CHN)
-
-#define I2C3_RX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \
- STM32_I2C3_RX_DMA_CHN)
-
-#define I2C3_TX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \
- STM32_I2C3_TX_DMA_CHN)
-
-/*===========================================================================*/
-/* Driver constants -- see ST document RM0038 figure 208 */
-/*===========================================================================*/
-#define I2C_EV5_MASTER_MODE_SELECT \
- (((uint32_t)I2C_SR2_MSL << 16) | I2C_SR1_SB)
-
-#define I2C_EV6_MASTER_TRA_MODE_SELECTED \
- (((uint32_t)(I2C_SR2_MSL | I2C_SR2_TRA) << 16) | I2C_SR1_ADDR)
-
-#define I2C_EV6_MASTER_REC_MODE_SELECTED \
- (((uint32_t)I2C_SR2_MSL << 16) | I2C_SR1_ADDR)
-
-#define I2C_EV8_2_MASTER_BYTE_TRANSMITTED \
- (((uint32_t)(I2C_SR2_MSL | I2C_SR2_TRA) << 16) | I2C_SR1_BTF)
-
-#define I2C_EV9_MASTER_ADD10 \
- ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_ADD10))
-
-#if HAL_USE_I2C_SLAVE
-#define I2C_EV1_SLAVE_RXADRMATCH \
- ((uint32_t)I2C_SR1_ADDR)
-
-#define I2C_EV1_SLAVE_TXADRMATCH \
- (((uint32_t)I2C_SR2_TRA << 16) | I2C_SR1_ADDR)
-
-#define I2C_EV2_SLAVE_RXSTOP \
- (I2C_SR1_STOPF)
-#endif
-
-#define I2C_EV_MASK ( \
- ((uint32_t)(I2C_SR2_MSL|I2C_SR2_TRA)<<16) | \
- (I2C_SR1_SB|I2C_SR1_ADDR|I2C_SR1_STOPF|I2C_SR1_BTF))
-
-#define I2C_ERROR_MASK \
- ((uint16_t)(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_OVR | \
- I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT))
-
-/*===========================================================================*/
-/* Driver exported variables. */
-/*===========================================================================*/
-
-/** @brief I2C1 driver identifier.*/
-#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__)
-I2CDriver I2CD1;
-#endif
-
-/** @brief I2C2 driver identifier.*/
-#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__)
-I2CDriver I2CD2;
-#endif
-
-/** @brief I2C3 driver identifier.*/
-#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__)
-I2CDriver I2CD3;
-#endif
-
-/* quick and dirty queue to record event interrupts */
-#define QEVENTS 32
-#if QEVENTS > 0
-typedef struct i2cQ_t {
- uint8_t code;
- uint8_t state;
- uint16_t param;
-} i2cQ_t;
-i2cQ_t i2cQ[QEVENTS];
-unsigned i2cI = QEVENTS;
-#define qEvt(posn,info) {if (++i2cI >= QEVENTS) i2cI = 0; \
- i2cQ[i2cI].code=(posn); i2cQ[i2cI].state=(i2cp->mode); i2cQ[i2cI].param=(info); }
-#else
-#define qEvt(posn,info)
-#endif
-
-
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
-
-void I2CSlaveDummyCB(I2CDriver *i2cp)
-/*
- dummy callback -- placeholder to ignore event
-*/
-{(void)i2cp;}
-
- /* lock bus on receive or reply message */
-const I2CSlaveMsg I2CSlaveLockOnMsg = {
- 0, NULL, I2CSlaveDummyCB, I2CSlaveDummyCB, I2CSlaveDummyCB
-};
-
-#endif
-
-/*===========================================================================*/
-/* Driver local functions. */
-/*===========================================================================*/
-
-/**
- * @brief Resets and disables the I2C channel
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void i2cReset(I2CDriver *i2cp) {
- I2C_TypeDef *dp = i2cp->i2c;
- /* reset the I2C registers.*/
- dp->CR1 = I2C_CR1_SWRST;
- dp->CR1 = 0;
- dp->CR2 = 0;
- dp->SR1 = 0;
-
- /* Stop the associated DMA streams.*/
- dmaStreamDisable(i2cp->dmatx);
- dmaStreamDisable(i2cp->dmarx);
-}
-
-/**
- * @brief Aborts an I2C transaction.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void i2cAbortOperation(I2CDriver *i2cp) {
- /* save control registers */
- I2C_TypeDef *dp = i2cp->i2c;
- uint16_t cr2 = dp->CR2, cr1 = dp->CR1;
-#if HAL_USE_I2C_SLAVE
- uint16_t oar1 = dp->OAR1, oar2 = dp->OAR2;
-#endif
- uint16_t ccr = dp->CCR, trise = dp->TRISE;
-
- /* reset the I2C channel */
- i2cReset(i2cp);
-
- /* restore control registers */
- dp->TRISE = trise; dp->CCR = ccr;
-#if HAL_USE_I2C_SLAVE
- /* restore address mataching */
- dp->OAR1 = oar1; dp->OAR2 = oar2;
-#endif
-
- /* Enable interrrupts */
- dp->CR2 = (cr2 & 0x3F) | I2C_CR2_ITERREN | I2C_CR2_DMAEN | I2C_CR2_ITEVTEN;
-
- /* Finish restoring and enable pheripheral */
- dp->CR1 = I2C_CR1_ACK | I2C_CR1_PE | (cr1 & (I2C_CR1_SMBUS | I2C_CR1_SMBTYPE))
-#if HAL_USE_I2C_SLAVE
- | (cr1 & I2C_CR1_ENGC)
-#endif
- ;
-}
-
-
-#if HAL_USE_I2C_SLAVE || HAL_USE_I2C_LOCK
-/**
- * @brief stop transaction timeout countdown
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static inline void stopTimer(I2CDriver *i2cp)
-{
- osalSysLockFromISR();
- chVTResetI(&i2cp->timer);
- osalSysUnlockFromISR();
-}
-#else
-#define stopTimer(ignored) {}
-#endif
-
-
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
-
-/**
- * @brief return the address matched
- *
- * @param[in] dp pointer to the @p I2C registers object
- * @param[in] sr2 I2C SR2 register contents
- *
- * @notapi
- * Only supports 7-bit addressing for now
- */
-static inline i2caddr_t matchedAdr(I2C_TypeDef *dp, uint32_t sr2) {
- if (sr2 & I2C_SR2_GENCALL)
- return 0;
- if (sr2 & I2C_SR2_DUALF)
- return (dp->OAR2>>1) & 0x7f;
- return (dp->OAR1>>1) & 0x7f;
-}
-
-
-/**
- * @brief report error via slave exception callback
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @note moves back to the idle mode
- * @notapi
- */
-static inline void reportSlaveError(I2CDriver *i2cp) {
-#if HAL_USE_I2C_STARTFIX
- i2cp->config->disarmStartDetect();
-#endif
- {
- const I2CSlaveMsg *xfer = i2cp->mode >= i2cSlaveReplying ?
- i2cp->slaveReply : i2cp->slaveRx;
- if (xfer->exception)
- xfer->exception(i2cp); /* in this case, i2cp->slaveErrors == 0 */
- }
- i2cp->mode = i2cIdle;
- i2cp->targetAdr = i2cInvalidAdr;
-}
-
-
-/**
- * @brief Handling of stalled slave mode I2C transactions.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void slaveTimeExpired(void *i2cv) {
- I2CDriver *i2cp = i2cv;
-
- if (i2cp->mode < i2cIsMaster)
- {
- i2cAbortOperation(i2cp);
- reportSlaveError(i2cp);
- }
-}
-
-
-/**
- * @brief start or restart slave mode transaction
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static inline void startSlaveAction(I2CDriver *i2cp, i2caddr_t targetAdr)
-{
- stopTimer(i2cp);
- i2cp->targetAdr = targetAdr;
- i2cp->slaveBytes = 0;
- i2cp->slaveErrors = 0;
- if (i2cp->slaveTimeout != TIME_INFINITE)
- {
- osalSysLockFromISR();
- chVTSetI(&i2cp->timer, i2cp->slaveTimeout, slaveTimeExpired, i2cp);
- osalSysUnlockFromISR();
- }
-}
-
-/**
- * @brief end slave receive message DMA
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static inline void endSlaveRxDMA(I2CDriver *i2cp)
-{
- size_t bytesRemaining = dmaStreamGetTransactionSize(i2cp->dmarx);
- if (i2cp->slaveBytes)
- i2cp->slaveBytes += 0xffff - bytesRemaining;
- else
- i2cp->slaveBytes = i2cp->slaveRx->size - bytesRemaining;
- dmaStreamDisable(i2cp->dmarx);
-}
-
-/**
- * @brief end slave transmit DMA
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] bytesRemaining bytes lost in output queue
- *
- * @notapi
- */
-static inline void endSlaveReplyDMA(I2CDriver *i2cp, size_t bytesRemaining)
-{
- bytesRemaining += dmaStreamGetTransactionSize(i2cp->dmatx);
- if (i2cp->slaveBytes)
- i2cp->slaveBytes += 0xffff - bytesRemaining;
- else
- i2cp->slaveBytes = i2cp->slaveReply->size - bytesRemaining;
- dmaStreamDisable(i2cp->dmatx);
-}
-
-#endif
-
-
-/**
- * @brief Wakes up a waiting thread.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] msg wakeup message
- *
- * @notapi
- */
-static inline void wakeup_isr(I2CDriver *i2cp, msg_t msg)
-{
- do {
- osalSysLockFromISR();
- osalThreadResumeI(&(i2cp)->thread, msg);
- osalSysUnlockFromISR();
- } while(0);
-
-#if 0
- chSysLockFromISR();
- thread_t *tp = i2cp->thread;
- if (tp != NULL) {
- i2cp->thread = NULL;
- tp->p_u.rdymsg = msg;
- chSchReadyI(tp);
- }
- chSysUnlockFromISR();
-#endif
-}
-
-
-/**
- * @brief Set clock speed.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void i2c_lld_set_clock(I2CDriver *i2cp) {
- I2C_TypeDef *dp = i2cp->i2c;
- uint16_t regCCR, clock_div;
- int32_t clock_speed = i2cp->config->clock_speed;
- i2cdutycycle_t duty = i2cp->config->duty_cycle;
-
- osalDbgCheck((i2cp != NULL) &&
- (clock_speed > 0) &&
- (clock_speed <= 4000000));
-
- /* CR2 Configuration.*/
- dp->CR2 &= (uint16_t)~I2C_CR2_FREQ;
- dp->CR2 |= (uint16_t)I2C_CLK_FREQ;
-
- /* CCR Configuration.*/
- regCCR = 0;
- clock_div = I2C_CCR_CCR;
-
- switch (duty) {
- case STD_DUTY_CYCLE:
- /* Standard mode clock_div calculate: Tlow/Thigh = 1/1.*/
-#ifndef STM32_I2C_LOOSE_CLK
- /* Configure clock_div in standard mode.*/
- osalDbgAssert(clock_speed <= 100000,
- "#1 - STD_DUTY_CYCLE limited to 100khz");
- osalDbgAssert(STM32_PCLK1 % (clock_speed * 2) == 0,
- "#2 - PCLK1 not divisible by 2*I2Cclk");
-#endif
- clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2));
-
-
- osalDbgAssert(clock_div >= 0x04,
- "clock divider less then 0x04 not allowed");
- regCCR |= (clock_div & I2C_CCR_CCR);
-
- /* Sets the Maximum Rise Time for standard mode.*/
- dp->TRISE = (uint16_t)(I2C_CLK_FREQ + 1);
- break;
-
- case FAST_DUTY_CYCLE_2:
- case FAST_DUTY_CYCLE_16_9:
- /* Configure clock_div in fast mode.*/
-#ifndef STM32_I2C_LOOSE_CLK
- osalDbgAssert(clock_speed > 100000 && clock_speed <= 400000,
- "#4 - I2Cclk out of range for FAST_DUTY_CYCLE");
-#endif
- if (duty == FAST_DUTY_CYCLE_2) {
- /* Fast mode clock_div calculate: Tlow/Thigh = 2/1.*/
-#ifndef STM32_I2C_LOOSE_CLK
- osalDbgAssert((STM32_PCLK1 % (clock_speed * 3)) == 0,
- "#6 - PCLK1 not divisible by 3*I2Cclk");
-#endif
- clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3));
- }else{ /* FAST_DUTY_CYCLE_16_9 */
- /* Fast mode clock_div calculate: Tlow/Thigh = 16/9.*/
-#ifndef STM32_I2C_LOOSE_CLK
- osalDbgAssert(STM32_PCLK1 % (clock_speed * 25) == 0,
- "#7 - PCLK1 not divisible by 25*I2Cclk");
-#endif
- clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25));
- regCCR |= I2C_CCR_DUTY;
- }
-
- osalDbgAssert(clock_div >= 0x01,
- "clock divider less then 0x04 not allowed");
- regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR));
-
- /* Sets the Maximum Rise Time for fast mode.*/
- dp->TRISE = (uint16_t)((I2C_CLK_FREQ * 300 / 1000) + 1);
- break;
-
- default:
- osalSysHalt("Invalid I2C duty_cycle");
- }
-
- osalDbgAssert((clock_div <= I2C_CCR_CCR), "the selected clock is too low");
-
- dp->CCR = (uint16_t)regCCR;
-}
-
-
-/**
- * @brief Set operation mode of I2C hardware.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void i2c_lld_set_opmode(I2CDriver *i2cp) {
- I2C_TypeDef *dp = i2cp->i2c;
- i2copmode_t opmode = i2cp->config->op_mode;
- uint16_t regCR1;
-
- regCR1 = dp->CR1;
- switch (opmode) {
- case OPMODE_I2C:
- regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE);
- break;
- case OPMODE_SMBUS_DEVICE:
- regCR1 |= I2C_CR1_SMBUS;
- regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE);
- break;
- case OPMODE_SMBUS_HOST:
- regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE);
- }
- dp->CR1 = (uint16_t)regCR1;
-}
-
-
-
-#if USE_OLD_MASTER_STARTUP
-/**
- * @brief Handling of stalled master mode I2C transactions.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void i2c_lld_safety_timeout(void *p) {
- I2CDriver *i2cp = p;
-
- stopTimer(i2cp);
-#if HAL_USE_I2C_SLAVE /* abort any slave operation in progress */
- if (!(i2cp->i2c->SR2 & I2C_SR2_MSL))
- slaveTimeExpired(i2cp); /* in case slave preventing master bus access */
- else
-#endif
- {
- i2cAbortOperation(i2cp);
- i2cp->mode = i2cIdle;
- }
- wakeup_isr(i2cp, I2C_ERR_TIMEOUT);
-}
-#endif
-
-
-#if HAL_USE_I2C_LOCK /* I2C bus locking support */
-
-/**
- * @brief Handling of expired master bus lock timer
- *
- * @param[in] i2cv pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void lockExpired(void *i2cv) {
- I2CDriver *i2cp = i2cv;
-
- if (i2cp->mode == i2cIsMaster && !i2cp->thread) { /* between transactions */
- i2cp->i2c->CR1 |= (uint16_t)(I2C_CR1_STOP | I2C_CR1_ACK);
- i2cp->mode = i2cIdle;
- }
- i2cp->lockDuration = TIME_IMMEDIATE;
-}
-
-
-/**
- * @brief Lock I2C bus at the beginning of the next message
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] lockDuration max number of ticks to hold bus locked
- * - @a TIME_INFINITE no timeout.
- * - @a TIME_IMMEDIATE unlock the bus immediately
- * .
- *
- * Lock I2C bus at the beginning of the next message sent
- * for a maximum of lockDuration ticks. No other I2C masters will
- * be allowed to interrupt until i2cUnlock() is called.
- *
- * @notapi
- **/
-void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration)
-{
- i2cp->lockDuration = lockDuration;
- if (i2cp->mode >= i2cIsMaster) {
- stopTimer(i2cp);
- if (lockDuration == TIME_IMMEDIATE)
- lockExpired(i2cp);
- else if (lockDuration != TIME_INFINITE)
- chVTSetI(&i2cp->timer, lockDuration, lockExpired, i2cp);
- }
-}
-
-#endif
-
-
-
-/**
- * @brief report error waking thread or invoking callback as appropriate
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] errCode error bit mask or code
- *
- * @notapi
- */
-static void reportErrs(I2CDriver *i2cp, i2cflags_t errCode)
-{
-qEvt(0xee,errCode);
- I2C_TypeDef *dp = i2cp->i2c;
- if (i2cp->mode <= i2cIdle) /* failing to master bus */
- i2cAbortOperation(i2cp);
- else if (dp->SR2 & I2C_SR2_MSL) {
-#if HAL_USE_I2C_LOCK /* I2C bus locking support */
- i2cp->mode = i2cIsMaster;
- switch (i2cp->lockDuration) {
- case TIME_INFINITE:
- break;
- case TIME_IMMEDIATE:
- stopTimer(i2cp);
- default:
- if (!chVTIsArmedI(&i2cp->timer)) {
- dp->CR1 |= (uint16_t)(I2C_CR1_STOP | I2C_CR1_ACK);
- i2cp->mode = i2cIdle;
- i2cp->lockDuration = TIME_IMMEDIATE;
- }
- }
-#else /* signal stop condition on any error */
- dp->CR1 |= (uint16_t)(I2C_CR1_STOP | I2C_CR1_ACK);
- i2cp->mode = i2cIdle;
-#endif
- }
-#if HAL_USE_I2C_SLAVE
- else if (i2cp->mode < i2cIsMaster) {
- i2cp->slaveErrors = errCode;
- i2cAbortOperation(i2cp);
- stopTimer(i2cp);
- reportSlaveError(i2cp);
- return;
- }
-#endif
- /* wake any waiting master mode handling thread. */
- i2cp->errors = errCode;
- wakeup_isr(i2cp, I2C_ERROR);
-}
-
-
-/**
- * @brief I2C error handler.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] sr content of the SR1 register to be decoded
- *
- * @notapi
- */
-static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) {
-#if HAL_USE_I2C_SLAVE
-/* NACK of last byte transmitted in slave response is NORMAL -- not an error! */
- if (i2cp->mode == i2cSlaveReplying && (sr & I2C_ERROR_MASK) == I2C_SR1_AF) {
-qEvt(0xcc,sr);
- endSlaveReplyDMA(i2cp, 1);
-#if HAL_USE_I2C_STARTFIX
- i2cp->config->disarmStartDetect();
-#endif
- if (i2cp->slaveReply->processMsg)
- i2cp->slaveReply->processMsg(i2cp);
- i2cp->targetAdr = i2cInvalidAdr;
- stopTimer(i2cp);
- i2cp->mode = i2cIdle;
- return;
- }
-#endif
- i2cflags_t errs = 0;
-
- if (sr & I2C_SR1_BERR) /* Bus error. */
- errs = I2C_BUS_ERROR;
-
- if (sr & I2C_SR1_ARLO) /* Arbitration lost. */
- errs |= I2C_ARBITRATION_LOST;
-
- if (sr & I2C_SR1_AF) /* Acknowledge fail. */
- errs |= I2C_ACK_FAILURE;
-
- if (sr & I2C_SR1_OVR) /* Overrun. */
- errs |= I2C_OVERRUN;
-
- if (sr & I2C_SR1_TIMEOUT) /* SMBus Timeout. */
- errs |= I2C_TIMEOUT;
-
- if (sr & I2C_SR1_PECERR) /* PEC error. */
- errs |= I2C_PEC_ERROR;
-
- if (sr & I2C_SR1_SMBALERT) /* SMBus alert. */
- errs |= I2C_SMB_ALERT;
-
- if (!errs)
- errs = I2C_UNKNOWN_ERROR;
-qEvt(0xcb,errs);
-
- /* Disable any active DMA */
- dmaStreamDisable(i2cp->dmatx);
- dmaStreamDisable(i2cp->dmarx);
-
- reportErrs(i2cp, errs);
-}
-
-
-static inline void endMasterAction(I2CDriver *i2cp, uint32_t regCR1)
-{
-#if HAL_USE_I2C_LOCK
- if (i2cp->lockDuration != TIME_IMMEDIATE && (
- chVTIsArmedI(&i2cp->timer) || i2cp->lockDuration == TIME_INFINITE)) {
- i2cp->mode = i2cIsMaster;
- return;
- }
- stopTimer(i2cp);
-#endif
- i2cp->i2c->CR1 = (regCR1 | I2C_CR1_STOP | I2C_CR1_ACK);
- i2cp->mode = i2cIdle;
-}
-
-
-/**
- * @brief I2C event handler ISR
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp)
-{
- I2C_TypeDef *dp = i2cp->i2c;
- uint16_t regCR1 = dp->CR1;
- uint32_t regSR2 = dp->SR2;
- uint32_t event = dp->SR1 | (regSR2 << 16);
-
-
- switch (event & I2C_EV_MASK) {
-
-#define chkTransition(expectedMode) { \
- if (i2cp->mode != (expectedMode)) goto invalidTransition;}
-
- invalidTransition: /* error on known event out of expected sequence */
- i2cAbortOperation(i2cp); /* reset and reinit */
- qEvt(0x10, (event & 0xffff));
- reportErrs(i2cp, I2C_UNKNOWN_ERROR + i2cp->mode);
- break;
-
-#if HAL_USE_I2C_SLAVE
- case I2C_EV1_SLAVE_RXADRMATCH : /* Slave mode - receive a message */
-qEvt(0x11,0);
- {
- i2caddr_t targetAdr = matchedAdr(dp, regSR2);
- switch (i2cp->mode) {
- case i2cIdle:
-#if HAL_USE_I2C_STARTFIX
- i2cp->config->armStartDetect();
-#endif
- break;
- case i2cSlaveRxing:
- endSlaveRxDMA(i2cp);
- if (i2cp->slaveRx->processMsg)
- i2cp->slaveRx->processMsg(i2cp);
- break;
- case i2cSlaveReplying: /* Master did not NACK last transmitted byte */
- endSlaveReplyDMA(i2cp, 2);
- if (i2cp->slaveReply->processMsg)
- i2cp->slaveReply->processMsg(i2cp);
- break;
- default:
- goto invalidTransition;
- }
- startSlaveAction(i2cp, targetAdr);
- }
- {
- const I2CSlaveMsg *rx = i2cp->slaveNextRx;
- if (rx->adrMatched) // Q: Can rx ever be NULL?
- rx->adrMatched(i2cp); // Execute callback on address match if specified
- rx = i2cp->slaveRx = i2cp->slaveNextRx;
- if (rx->body && rx->size) {
- (void)dp->SR2; /* clear I2C_SR1_ADDR */
- /* Receive buffer available - can receive immediately. Set up slave RX DMA */
- dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
- dmaStreamSetMemory0(i2cp->dmarx, rx->body);
- dmaStreamSetTransactionSize(i2cp->dmarx, rx->size);
- dmaStreamEnable(i2cp->dmarx);
- i2cp->mode = i2cSlaveRxing;
- }else{
- dp->CR2 &= (uint16_t)(~I2C_CR2_ITEVTEN); /* No reply set up - hold clock low and wait */
- i2cp->mode = i2cLockedRxing;
- }
- }
- break;
-
- case I2C_EV2_SLAVE_RXSTOP: /* STOP received - possibly without NAK */
-qEvt(0x22,0);
- dp->CR1 = (uint16_t)regCR1; /* clear STOPF */
- i2cp->slaveErrors = I2C_STOPPED; /* indicate that bus has been released */
- switch (i2cp->mode) {
- case i2cSlaveRxing:
- endSlaveRxDMA(i2cp);
- if (i2cp->slaveRx->processMsg)
- i2cp->slaveRx->processMsg(i2cp);
- break;
- case i2cSlaveReplying: /* Master did not NACK last transmitted byte */
- endSlaveReplyDMA(i2cp, 2);
- if (i2cp->slaveReply->processMsg)
- i2cp->slaveReply->processMsg(i2cp);
- break;
- default:
- goto invalidTransition;
- }
-#if HAL_USE_I2C_STARTFIX
- i2cp->config->disarmStartDetect();
-#endif
- i2cp->targetAdr = i2cInvalidAdr;
- stopTimer(i2cp);
- i2cp->mode = i2cIdle;
- break;
-
- case I2C_EV1_SLAVE_TXADRMATCH: /* Slave mode - reply */
-qEvt(0x33,0);
- {
- i2caddr_t targetAdr = matchedAdr(dp, regSR2);
- (void)dp->SR2; /* clear I2C_SR1_ADDR */ // TODO: Check
- switch (i2cp->mode) {
- case i2cIdle:
-#if HAL_USE_I2C_STARTFIX
- i2cp->config->armStartDetect();
-#endif
- break;
- case i2cSlaveRxing: /* Previous transaction not completed properly */
- endSlaveRxDMA(i2cp);
- if (i2cp->slaveRx->processMsg)
- i2cp->slaveRx->processMsg(i2cp);
- break;
- default:
- goto invalidTransition;
- }
- startSlaveAction(i2cp, targetAdr);
- }
- {
- const I2CSlaveMsg *reply = i2cp->slaveNextReply;
- if (reply->adrMatched) // Q: Can reply be NULL?
- reply->adrMatched(i2cp);
- reply = i2cp->slaveReply = i2cp->slaveNextReply; // Q: Duplicate action?
- if (reply->body && reply->size) {
- /* Reply message available - can send immediately. Set up slave TX DMA */
- dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
- dmaStreamSetMemory0(i2cp->dmatx, reply->body);
- dmaStreamSetTransactionSize(i2cp->dmatx, reply->size);
- dmaStreamEnable(i2cp->dmatx);
- i2cp->mode = i2cSlaveReplying;
- }else{
- dp->CR2 &= (uint16_t)(~I2C_CR2_ITEVTEN);
- i2cp->mode = i2cLockedReplying;
- }
- }
- break;
-#endif /* HAL_USE_I2C_SLAVE */
-
- case I2C_EV5_MASTER_MODE_SELECT:
-qEvt(0x55,0);
- dp->DR = (uint16_t)i2cp->addr;
- switch (i2cp->mode) {
- case i2cIdle:
-#if HAL_USE_I2C_LOCK
- {
- systime_t lockDuration = i2cp->lockDuration;
- if (lockDuration != TIME_IMMEDIATE && lockDuration != TIME_INFINITE)
- {
- osalSysLockFromISR();
- chVTSetI(&i2cp->timer, lockDuration, lockExpired, i2cp);
- osalSysUnlockFromISR();
- }
- }
-#endif
- break;
- case i2cIsMaster:
- case i2cMasterStarted:
- break;
- default:
- goto invalidTransition;
- }
- i2cp->mode = i2cMasterSelecting;
- break;
-
- case I2C_EV6_MASTER_REC_MODE_SELECTED:
-qEvt(0x66,0);
- chkTransition(i2cMasterSelecting);
- if (!i2cp->masterRxbytes) { /* 0-length SMBus style quick read */
- endMasterAction(i2cp, regCR1);
- (void)dp->SR2; /* clear I2C_SR1_ADDR */
- wakeup_isr(i2cp, I2C_OK);
- break;
- }
- (void)dp->SR2; /* clear I2C_SR1_ADDR */
- /* RX DMA setup.*/
- dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
- dmaStreamSetMemory0(i2cp->dmarx, i2cp->masterRxbuf);
- dmaStreamSetTransactionSize(i2cp->dmarx, i2cp->masterRxbytes);
- dmaStreamEnable(i2cp->dmarx);
- dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */
- if (i2cp->masterRxbytes < 2)
- dp->CR1 = (uint16_t)(regCR1 & ~I2C_CR1_ACK);
- i2cp->mode = i2cMasterRxing;
- break;
-
- case I2C_EV6_MASTER_TRA_MODE_SELECTED:
-qEvt(0x77,0);
- (void)dp->SR2; /* clear I2C_SR1_ADDR */
- chkTransition(i2cMasterSelecting);
- switch (i2cp->masterTxbytes) {
- case 0:
- goto doneWriting;
- case 1:
- dp->DR = i2cp->masterTxbuf[0];
- break;
- case 2:
- dp->DR = i2cp->masterTxbuf[0];
- dp->DR = i2cp->masterTxbuf[1];
- break;
- default:
- /* TX DMA setup.*/
- dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
- dmaStreamSetMemory0(i2cp->dmatx, i2cp->masterTxbuf);
- dmaStreamSetTransactionSize(i2cp->dmatx, i2cp->masterTxbytes);
- dmaStreamEnable(i2cp->dmatx);
- }
- i2cp->mode = i2cMasterTxing;
- break;
-
- case I2C_EV8_2_MASTER_BYTE_TRANSMITTED:
-qEvt(0x88,0);
- /* Catches BTF event after the end of transmission.*/
- (void)dp->DR; /* clears BTF flag */
- chkTransition(i2cMasterTxing);
-doneWriting:
- if (i2cp->masterRxbuf) {
- /* Starts "read after write" operation, LSB = 1 -> receive.*/
- dp->CR1 = (uint16_t)(regCR1 | I2C_CR1_START | I2C_CR1_ACK);
- i2cp->addr |= 1;
- i2cp->mode = i2cMasterStarted;
- }else{
- endMasterAction(i2cp, regCR1);
- wakeup_isr(i2cp, I2C_OK);
- }
- break;
-
- case 0: /* quietly ignore "uninteresting" events (i.e. i2c bus busy) */
- qEvt(0x0000);
- break;
-
- default: /* unhandled event -- abort transaction, flag unknown err */
-qEvt(0x9999,0);
- //i2cAbortOperation(i2cp);
- i2c_lld_serve_error_interrupt(i2cp, event);
- }
-}
-
-
-#if HAL_USE_I2C_STARTFIX
-/**
- * @brief external device detected start condition
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @details invoked from ISR if a START CONDITION detected during the time
- * the startDetector is armed.
- * This is a workaround for the STM32's lack of a repeated start event
- *
- * @notapi
- */
-void i2c_lld_startDetected(I2CDriver *i2cp)
-{
-qEvt(0xdddd,0);
- switch (i2cp->mode) {
- case i2cIdle:
- i2cAbortOperation(i2cp); /* quietly reset and reinit */
- return;
- case i2cSlaveRxing:
- endSlaveRxDMA(i2cp);
- if (i2cp->slaveRx->processMsg)
- i2cp->slaveRx->processMsg(i2cp);
- break;
- case i2cSlaveReplying: /* Master did not NACK last transmitted byte */
- endSlaveReplyDMA(i2cp, 2);
- if (i2cp->slaveReply->processMsg)
- i2cp->slaveReply->processMsg(i2cp);
- break;
- default:
- i2cAbortOperation(i2cp); /* reset and reinit */
- reportErrs(i2cp, I2C_UNKNOWN_ERROR + i2cp->mode);
- return;
- }
- i2cp->targetAdr = i2cInvalidAdr;
- stopTimer(i2cp);
- i2cp->mode = i2cIdle;
-}
-
-/**
- * @brief dummy placeholder for armStartDetector() and disarmStartDetector()
- *
- * @details *MUST* be placed in the configuration struct in cases where
- * HAL_USE_I2C_STARTFIX is configured and no startDetector is defined,
- * otherwise NULL pointers will be called for these functions!
- *
- * @notapi
- */
-void i2c_lld_noStartDetector(void) {}
-#endif
-
-
-/**
- * @brief DMA RX end IRQ handler.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] flags pre-shifted content of the ISR register
- *
- * @notapi
- */
-static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) {
- I2C_TypeDef *dp = i2cp->i2c;
-
-qEvt(0xaa,0);
- /* DMA errors handling.*/
-#if defined(STM32_I2C_DMA_ERROR_HOOK)
- if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
- STM32_I2C_DMA_ERROR_HOOK(i2cp);
- }
-#else
- (void)flags;
-#endif
-
- dmaStreamDisable(i2cp->dmarx);
-
-#if HAL_USE_I2C_SLAVE
- if (i2cp->mode < i2cIsMaster) {
- static uint8_t bitbucket;
- if (i2cp->slaveBytes)
- i2cp->slaveBytes += 0xffff; // TODO: Why?? (slaveBytes is uint32)
- else
- i2cp->slaveBytes = i2cp->slaveRx->size;
- /* discard data overrunning available rx buffer, but record total length */
- dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode & ~STM32_DMA_CR_MINC);
- dmaStreamSetMemory0(i2cp->dmarx, &bitbucket);
- dmaStreamSetTransactionSize(i2cp->dmarx, 0xffff);
- dmaStreamEnable(i2cp->dmarx);
- return;
- }
-#endif
-
- dp->CR2 &= (uint16_t)(~I2C_CR2_LAST);
- endMasterAction(i2cp, dp->CR1);
- wakeup_isr(i2cp, I2C_OK);
-}
-
-/**
- * @brief DMA TX end IRQ handler.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) {
-qEvt(0xbb,0);
- /* DMA errors handling.*/
-#if defined(STM32_I2C_DMA_ERROR_HOOK)
- if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
- STM32_I2C_DMA_ERROR_HOOK(i2cp);
- }
-#else
- (void)flags;
-#endif
- dmaStreamDisable(i2cp->dmatx);
-
-#if HAL_USE_I2C_SLAVE
- if (i2cp->mode < i2cIsMaster) {
- const I2CSlaveMsg *reply = i2cp->slaveReply;
- if (i2cp->slaveBytes)
- i2cp->slaveBytes += 0xffff; // TODO: Why?? (slaveBytes is uint32)
- else
- i2cp->slaveBytes = reply->size;
- /* repeat the last byte in the reply */
- dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode & ~STM32_DMA_CR_MINC);
- dmaStreamSetMemory0(i2cp->dmatx, reply->body+reply->size-1);
- dmaStreamSetTransactionSize(i2cp->dmatx, 0xffff);
- dmaStreamEnable(i2cp->dmatx);
- }
-#endif
-}
-
-/*===========================================================================*/
-/* Driver interrupt handlers. */
-/*===========================================================================*/
-
-#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__)
-/**
- * @brief I2C1 event interrupt handler.
- *
- * @notapi
- */
-OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) {
-
- OSAL_IRQ_PROLOGUE();
-
- i2c_lld_serve_event_interrupt(&I2CD1);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-/**
- * @brief I2C1 error interrupt handler.
- */
-OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) {
- uint16_t sr = I2CD1.i2c->SR1;
-
- OSAL_IRQ_PROLOGUE();
-
- I2CD1.i2c->SR1 = ~(sr & I2C_ERROR_MASK);
- i2c_lld_serve_error_interrupt(&I2CD1, sr);
-
- OSAL_IRQ_EPILOGUE();
-}
-#endif /* STM32_I2C_USE_I2C1 */
-
-#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__)
-/**
- * @brief I2C2 event interrupt handler.
- *
- * @notapi
- */
-OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) {
-
- OSAL_IRQ_PROLOGUE();
-
- i2c_lld_serve_event_interrupt(&I2CD2);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-/**
- * @brief I2C2 error interrupt handler.
- *
- * @notapi
- */
-OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) {
- uint16_t sr = I2CD2.i2c->SR1;
-
- OSAL_IRQ_PROLOGUE();
-
- I2CD2.i2c->SR1 = ~(sr & I2C_ERROR_MASK);
- i2c_lld_serve_error_interrupt(&I2CD2, sr);
-
- OSAL_IRQ_EPILOGUE();
-}
-#endif /* STM32_I2C_USE_I2C2 */
-
-#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__)
-/**
- * @brief I2C3 event interrupt handler.
- *
- * @notapi
- */
-OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) {
-
- OSAL_IRQ_PROLOGUE();
-
- i2c_lld_serve_event_interrupt(&I2CD3);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-/**
- * @brief I2C3 error interrupt handler.
- *
- * @notapi
- */
-OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) {
- uint16_t sr = I2CD3.i2c->SR1;
-
- OSAL_IRQ_PROLOGUE();
-
- I2CD3.i2c->SR1 = ~(sr & I2C_ERROR_MASK);
- i2c_lld_serve_error_interrupt(&I2CD3, sr);
-
- OSAL_IRQ_EPILOGUE();
-}
-#endif /* STM32_I2C_USE_I2C3 */
-
-/*===========================================================================*/
-/* Driver exported functions. */
-/*===========================================================================*/
-
-/**
- * @brief Low level I2C driver initialization.
- *
- * @notapi
- */
-void i2c_lld_init(void) {
-
-#if STM32_I2C_USE_I2C1
- i2cObjectInit(&I2CD1);
- I2CD1.thread = NULL;
- I2CD1.i2c = I2C1;
- I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM);
- I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM);
-#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE
- chVTObjectInit(&I2CD1.timer);
-#endif
-#endif /* STM32_I2C_USE_I2C1 */
-
-#if STM32_I2C_USE_I2C2
- i2cObjectInit(&I2CD2);
- I2CD2.thread = NULL;
- I2CD2.i2c = I2C2;
- I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM);
- I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM);
-#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE
- chVTObjectInit(&I2CD2.timer);
-#endif
-#endif /* STM32_I2C_USE_I2C2 */
-
-#if STM32_I2C_USE_I2C3
- i2cObjectInit(&I2CD3);
- I2CD3.thread = NULL;
- I2CD3.i2c = I2C3;
- I2CD3.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM);
- I2CD3.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM);
-#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE
- chVTObjectInit(&I2CD3.timer);
-#endif
-#endif /* STM32_I2C_USE_I2C3 */
-}
-
-/**
- * @brief Configures and activates the I2C peripheral.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-void i2c_lld_start(I2CDriver *i2cp) {
- I2C_TypeDef *dp = i2cp->i2c;
-
- i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
- STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
- STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
- STM32_DMA_CR_DIR_M2P;
- i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
- STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
- STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
- STM32_DMA_CR_DIR_P2M;
-
- /* If in stopped state then enables the I2C and DMA clocks.*/
- if (i2cp->state == I2C_STOP) {
-
-#if STM32_I2C_USE_I2C1
- if (&I2CD1 == i2cp) {
- bool b;
-
- rccResetI2C1(); // **** From trunk
- b = dmaStreamAllocate(i2cp->dmarx,
- STM32_I2C_I2C1_IRQ_PRIORITY,
- (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
- b = dmaStreamAllocate(i2cp->dmatx,
- STM32_I2C_I2C1_IRQ_PRIORITY,
- (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
- rccEnableI2C1(FALSE);
- nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY);
- nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY);
-
- i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
- i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
- }
-#endif /* STM32_I2C_USE_I2C1 */
-
-#if STM32_I2C_USE_I2C2
- if (&I2CD2 == i2cp) {
- bool b;
-
- rccResetI2C2(); // *** From trunk
- b = dmaStreamAllocate(i2cp->dmarx,
- STM32_I2C_I2C2_IRQ_PRIORITY,
- (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
- b = dmaStreamAllocate(i2cp->dmatx,
- STM32_I2C_I2C2_IRQ_PRIORITY,
- (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
- rccEnableI2C2(FALSE);
- nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY);
- nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY);
-
- i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
- i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
- }
-#endif /* STM32_I2C_USE_I2C2 */
-
-#if STM32_I2C_USE_I2C3
- if (&I2CD3 == i2cp) {
- bool b;
-
- rccResetI2C3(); // *** From trunk
- b = dmaStreamAllocate(i2cp->dmarx,
- STM32_I2C_I2C3_IRQ_PRIORITY,
- (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
- b = dmaStreamAllocate(i2cp->dmatx,
- STM32_I2C_I2C3_IRQ_PRIORITY,
- (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
- rccEnableI2C3(FALSE);
- nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY);
- nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY);
-
- i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
- i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
- }
-#endif /* STM32_I2C_USE_I2C3 */
- }
-
- /* I2C registers pointed by the DMA.*/
- dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
- dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
-
- /* Reset i2c peripheral.*/
- dp->CR1 = I2C_CR1_SWRST;
- dp->CR1 = 0;
-
- i2cp->mode = i2cIdle;
-#if HAL_USE_I2C_LOCK
- i2cp->lockDuration = TIME_IMMEDIATE;
-#endif
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
- i2cp->slaveNextReply = i2cp->slaveNextRx = &I2CSlaveLockOnMsg;
- i2cp->targetAdr = i2cInvalidAdr;
- i2cp->slaveTimeout = TIME_INFINITE;
-#endif
-
- /* Setup I2C parameters.*/
- i2c_lld_set_clock(i2cp);
- i2c_lld_set_opmode(i2cp);
-
- /* Enable interrrupts */
- dp->CR2 |= I2C_CR2_ITERREN | I2C_CR2_DMAEN | I2C_CR2_ITEVTEN;
- /* Ready to go.*/
- dp->CR1 |= I2C_CR1_PE | I2C_CR1_ACK;
-}
-
-/**
- * @brief Deactivates the I2C peripheral.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-void i2c_lld_stop(I2CDriver *i2cp) {
-
- /* If not in stopped state, then disable the I2C clock.*/
- if (i2cp->state != I2C_STOP) {
-
- /* I2C disable.*/
- i2cReset(i2cp);
- dmaStreamRelease(i2cp->dmatx);
- dmaStreamRelease(i2cp->dmarx);
-
-#if STM32_I2C_USE_I2C1
- if (&I2CD1 == i2cp) {
- nvicDisableVector(I2C1_EV_IRQn);
- nvicDisableVector(I2C1_ER_IRQn);
- rccDisableI2C1(FALSE);
- }
-#endif
-
-#if STM32_I2C_USE_I2C2
- if (&I2CD2 == i2cp) {
- nvicDisableVector(I2C2_EV_IRQn);
- nvicDisableVector(I2C2_ER_IRQn);
- rccDisableI2C2(FALSE);
- }
-#endif
-
-#if STM32_I2C_USE_I2C3
- if (&I2CD3 == i2cp) {
- nvicDisableVector(I2C3_EV_IRQn);
- nvicDisableVector(I2C3_ER_IRQn);
- rccDisableI2C3(FALSE);
- }
-#endif
-
- reportErrs(i2cp, I2C_STOPPED); /* wake any blocked thread */
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
- reportErrs(i2cp, I2C_STOPPED); /* ensure both master and slave notified */
-#endif
- }
-}
-
-
-/**
- * @brief Starts an I2C bus master transaction.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @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 I2C_OK if the function succeeded.
- * @retval I2C_ERROR if one or more I2C errors occurred, the errors can
- * be retrieved using @p i2cGetErrors().
- * @retval I2C_ERR_TIMEOUT A timeout occurred before operation end. After a
- * timeout the driver should be stopped and restarted
- * because the bus may in an uncertain state.
- * Drivers that support slave mode require only the the driver be restarted
- * after a timeout, as stopping and restarting may result in missed events.
- *
- * There's a system lock active from higher levels when this is called
- *
- * @notapi
- */
-#if USE_OLD_MASTER_STARTUP
-// This is the 'original' from the V2.x master/slave code
-static msg_t startMasterAction(I2CDriver *i2cp, systime_t timeout)
-{
- osalDbgAssert((i2cp->mode <= i2cIsMaster), "busy");
-
- i2cp->i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
-
- virtual_timer_t vt; /* Global timeout for the whole operation.*/
- chVTObjectInit(&vt);
-
- if (timeout != TIME_INFINITE)
- chVTSetI(&vt, timeout, i2c_lld_safety_timeout, i2cp);
- i2cp->errors = 0;
- i2cp->thread = chThdGetSelfX();
- chSchGoSleepS(CH_STATE_SUSPENDED);
- chVTResetI(&vt);
- return chThdGetSelfX()->p_u.rdymsg;
-}
-
-
-#else
-
-
-
-// This version uses same logic as the 'original' V3.x master-only driver.
-// Note: may need adjustment to work in multi-master mode as well - see i2c_lld_safety_timeout()
-static msg_t startMasterAction(I2CDriver *i2cp, systime_t timeout)
-{
- systime_t start, end;
-
- osalDbgAssert((i2cp->mode <= i2cIsMaster), "busy");
-
- osalSysUnlock();
-
- /* Calculating the time window for the timeout on the busy bus condition.*/
- start = osalOsGetSystemTimeX();
- end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT);
-
- /* Waits until BUSY flag is reset or, alternatively, for a timeout
- condition.*/
- while (true) {
- osalSysLock();
-
- /* If the bus is not busy then the operation can continue, note, the
- loop is exited in the locked state.*/
- if (!(i2cp->i2c->SR2 & I2C_SR2_BUSY) && !(i2cp->i2c->CR1 & I2C_CR1_STOP))
- break;
-
- /* If the system time went outside the allowed window then a timeout
- condition is returned.*/
- if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end))
- return MSG_TIMEOUT;
-
- osalSysUnlock();
- }
-
-
- i2cp->i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
-
- /* Waits for the operation completion or a timeout.*/
- return osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
-}
-#endif
-
-/**
- * @brief Receives data via the I2C bus as master.
- * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x.
- * This is hardware restriction.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] addr slave device address
- * @param[out] rxbuf pointer to the receive buffer
- * @param[in] rxbytes number of bytes to be received
- * @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 I2C_OK if the function succeeded.
- * @retval I2C_ERROR if one or more I2C errors occurred, the errors can
- * be retrieved using @p i2cGetErrors().
- * @retval I2C_ERR_TIMEOUT A timeout occurred before operation end. After a
- * timeout the driver should be stopped and restarted
- * because the bus may in an uncertain state.
- * Drivers that support slave mode require only the the driver be restarted
- * after a timeout, as stopping and restarting may result in missed events.
- *
- * @notapi
- */
-msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
- uint8_t *rxbuf, size_t rxbytes,
- systime_t timeout) {
- osalDbgAssert((rxbytes < (1<<16)),
- "#1 - >64Kbytes");
-#if defined(STM32F1XX_I2C)
- osalDbgAssert((rxbytes != 1),
- "#2 - rxbytes==1");
-#endif
- osalDbgAssert((i2cp->thread==NULL),
- "#3 - reentry");
-
- /* Initializes driver fields, LSB = 1 -> receive.*/
- i2cp->addr = (addr << 1) | 1;
-
- /* store away DMA info for later activation in event ISR */
- i2cp->masterRxbuf = rxbuf;
- i2cp->masterRxbytes = (uint16_t) rxbytes;
- return startMasterAction(i2cp, timeout);
-}
-
-/**
- * @brief Transmits data via the I2C bus as master.
- * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x.
- * This is hardware restriction.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] addr slave device address
- * @param[in] txbuf pointer to the transmit buffer
- * @param[in] txbytes number of bytes to be transmitted
- * @param[out] rxbuf pointer to the receive buffer
- * @param[in] rxbytes number of bytes to be received
- * @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 I2C_OK if the function succeeded.
- * @retval I2C_ERROR if one or more I2C errors occurred, the errors can
- * be retrieved using @p i2cGetErrors().
- * @retval I2C_ERR_TIMEOUT A timeout occurred before operation end. After a
- * timeout the driver should be stopped and restarted
- * because the bus is in an uncertain state.
- * Drivers that support slave mode require only the the driver be restarted
- * after a timeout, as stopping and restarting may result in missed events.
- *
- * There's a system lock active on entry from higher level driver
- *
- * @notapi
- */
-msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
- const uint8_t *txbuf, size_t txbytes,
- uint8_t *rxbuf, size_t rxbytes,
- systime_t timeout) {
- if (rxbuf == NULL)
- rxbytes = 0;
- osalDbgAssert(((rxbytes | txbytes) < (1<<16)), "#1 - >64Kbytes");
-#if defined(STM32F1XX_I2C)
- osalDbgCheck((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL)));
-#endif
- osalDbgAssert((i2cp->thread==NULL), "#3 - reentry");
-
- /* Initializes driver fields, LSB = 0 -> write.*/
- i2cp->addr = addr << 1;
- /* store away DMA info for later activation in event ISR */
- i2cp->masterTxbuf = txbuf;
- i2cp->masterTxbytes = (uint16_t) txbytes;
- i2cp->masterRxbuf = rxbuf;
- i2cp->masterRxbytes = (uint16_t) rxbytes;
- return startMasterAction(i2cp, timeout);
-}
-
-
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
-
-/* These bits are undocumented, but used in STM32l1xx I2C example driver */
-#define I2C_OAR1_Ack_7bit (0x4000) /*enable 7 bit address acknowledge*/
-#define I2C_OAR1_Ack_10bit (0xC000) /*enable 10 bit address acknowledge*/
-
-/**
- * @brief Reconfigure I2C channel to respond to indicated address
- * in addition to those already matched
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cadr I2C network address
- *
- * @return Length of message OR the type of event received
- * @retval I2C_OK Success
- * @retval I2C_ERROR Cannot match address in addition of those already
- *
- * @details MatchAddress calls are cumulative.
- * Specify address zero to match I2C "all call"
- * Does not support 10-bit addressing.
- *
- * @notapi
- **/
-msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr)
-{
- I2C_TypeDef *dp = i2cp->i2c;
- if (i2cadr == 0) {
- dp->CR1 |= I2C_CR1_ENGC;
- dp->OAR1 |= I2C_OAR1_Ack_7bit;
- }else{
- uint16_t adr = i2cadr << 1;
- uint16_t ownAdr = dp->OAR1 & (0x7f<<1);
- if (ownAdr == 0 || ownAdr == adr)
- dp->OAR1 = adr | I2C_OAR1_Ack_7bit;
- else if (!(dp->OAR2 & I2C_OAR2_ENDUAL))
- dp->OAR2 = adr | I2C_OAR2_ENDUAL;
- else if ((dp->OAR2 & (0x7f<<1)) != adr)
- return I2C_ERROR; /* cannot add this address to set of those matched */
- }
- return I2C_OK;
-}
-
-
-/**
- * @brief Reconfigure I2C channel to no longer match specified address
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cadr I2C network address
- *
- * @details A message being transferred that has already matched the
- * specified address will continue being processed.
- * Requests to unmatch an address that is not currently being matched
- * are ignored.
- * Does not support 10-bit addressing.
- *
- * @notapi
- **/
-void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr)
-{
- I2C_TypeDef *dp = i2cp->i2c;
- if (i2cadr == 0) {
- dp->CR1 &= (uint16_t)~I2C_CR1_ENGC;
- if ((dp->OAR1 & (0x7f<<1)) == 0)
- dp->OAR1 = 0;
- }else{
- uint16_t adr = i2cadr << 1;
- if ((dp->OAR1 & (0x7f<<1)) == adr) {
- if (dp->OAR2 & I2C_OAR2_ENDUAL)
- dp->OAR1 = (dp->OAR2 & (0x7f<<1)) | I2C_OAR1_Ack_7bit;
- else
- dp->OAR1 = dp->CR1 & I2C_CR1_ENGC ? I2C_OAR1_Ack_7bit : 0;
- }else if (dp->OAR2 & I2C_OAR2_ENDUAL && (dp->OAR2 & (0x7f<<1)) == adr)
- dp->OAR2 &= ~I2C_OAR2_ENDUAL;
- }
-}
-
-
-/**
- * @brief Reconfigure I2C channel to no longer match any address
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @details Causes all subsequent messages to be ignored.
- * A message being transferred that has already matched a
- * slave address will continue being processed.
- *
- * @notapi
- **/
-void i2c_lld_unmatchAll(I2CDriver *i2cp)
-{
- I2C_TypeDef *dp = i2cp->i2c;
- dp->CR1 &= (uint16_t)~I2C_CR1_ENGC;
- dp->OAR1 = 0;
- dp->OAR2 = 0;
-}
-
-
-/**
- * @brief Configure callbacks & buffers to receive messages
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent received messages
- *
- * @details Call i2cMatchAddress() after this to start processing
- * Enabling match addresses before installing handler callbacks can
- * result in locking the I2C bus when a master accesses those
- * unconfigured slave addresses
- *
- * @notapi
- */
-void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg)
-{
- osalDbgCheck((rxMsg && rxMsg->size <= 0xffff));
- i2cp->slaveNextRx = rxMsg;
- if (i2cp->mode == i2cLockedRxing && rxMsg->body && rxMsg->size) {
- /* We can receive now! */
- I2C_TypeDef *dp = i2cp->i2c;
- (void)dp->SR1, dp->SR2; /* clear I2C_SR1_ADDR */
- i2cp->slaveRx = rxMsg;
- /* slave RX DMA setup */
- dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
- dmaStreamSetMemory0(i2cp->dmarx, rxMsg->body);
- dmaStreamSetTransactionSize(i2cp->dmarx, rxMsg->size);
- dmaStreamEnable(i2cp->dmarx);
- i2cp->mode = i2cSlaveRxing;
- dp->CR2 |= I2C_CR2_ITEVTEN;
- }
-}
-
-
-/**
- * @brief Configure callbacks & buffers for query reply
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries
- *
- * @details Call i2cMatchAddress() after this to start processing
- * Enabling match addresses before installing handler callbacks can
- * result in locking the I2C bus when a master accesses those
- * unconfigured slave addresses
- *
- * @notapi
- */
-void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg)
-{
- osalDbgCheck((replyMsg && replyMsg->size <= 0xffff));
- i2cp->slaveNextReply = replyMsg;
- if (i2cp->mode == i2cLockedReplying && replyMsg->body && replyMsg->size) {
- i2cp->slaveReply = replyMsg;
- /* slave TX DMA setup -- we can reply now! */
- dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
- dmaStreamSetMemory0(i2cp->dmatx, replyMsg->body);
- dmaStreamSetTransactionSize(i2cp->dmatx, replyMsg->size);
- dmaStreamEnable(i2cp->dmatx);
- i2cp->mode = i2cSlaveReplying;
- i2cp->i2c->CR2 |= I2C_CR2_ITEVTEN;
- }
-}
-
-#endif /* HAL_USE_I2C_SLAVE */
-
-#endif /* HAL_USE_I2C */
-
-/** @} */
diff --git a/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h b/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h
deleted file mode 100644
index d45acaa671..0000000000
--- a/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h
+++ /dev/null
@@ -1,777 +0,0 @@
-/*
- ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-/*
- Concepts and parts of this file have been contributed by Uladzimir Pylinsky
- aka barthess. I2C Slave API contributed by Brent Roman (brent@mbari.org)
- */
-
-/**
- * @file STM32/I2Cv1/i2c_lld.h
- * @brief STM32 I2C subsystem low level driver header.
- *
- * @addtogroup I2C
- * @{
- */
-
-#ifndef _I2C_LLD_H_
-#define _I2C_LLD_H_
-
-#if HAL_USE_I2C || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver constants. */
-/*===========================================================================*/
-
-/**
- * @brief Peripheral clock frequency.
- */
-#define I2C_CLK_FREQ ((STM32_PCLK1) / 1000000)
-
-/**
- * @brief Invalid I2C bus address
- */
-#define i2cInvalidAdr ((i2caddr_t) -1)
-
-
-/*===========================================================================*/
-/* Driver pre-compile time settings. */
-/*===========================================================================*/
-
-/**
- * @name Configuration options
- * @{
- */
-/**
- * @brief I2C1 driver enable switch.
- * @details If set to @p TRUE the support for I2C1 is included.
- * @note The default is @p FALSE.
- */
-#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__)
-#define STM32_I2C_USE_I2C1 FALSE
-#endif
-
-/**
- * @brief I2C2 driver enable switch.
- * @details If set to @p TRUE the support for I2C2 is included.
- * @note The default is @p FALSE.
- */
-#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__)
-#define STM32_I2C_USE_I2C2 FALSE
-#endif
-
-/**
- * @brief I2C3 driver enable switch.
- * @details If set to @p TRUE the support for I2C3 is included.
- * @note The default is @p FALSE.
- */
-#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__)
-#define STM32_I2C_USE_I2C3 FALSE
-#endif
-
-/**
- * @brief Enables support for I2C slave mode operation
- */
-#if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__)
-#define HAL_USE_I2C_SLAVE FALSE
-#define HAL_USE_I2C_STARTFIX FALSE
-#endif
-
-/**
- * @brief Enables additional code needed with V1 I2C
- */
-#if !defined(HAL_USE_I2C_STARTFIX) || defined(__DOXYGEN__)
-#define HAL_USE_I2C_STARTFIX FALSE
-#endif
-
-
-/**
- * @brief I2C timeout on busy condition in milliseconds.
- */
-#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__)
-#define STM32_I2C_BUSY_TIMEOUT 50
-#endif
-
-/**
- * @brief I2C1 interrupt priority level setting.
- */
-#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C1_IRQ_PRIORITY 10
-#endif
-
-/**
- * @brief I2C2 interrupt priority level setting.
- */
-#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C2_IRQ_PRIORITY 10
-#endif
-
-/**
- * @brief I2C3 interrupt priority level setting.
- */
-#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C3_IRQ_PRIORITY 10
-#endif
-
-/**
-* @brief I2C1 DMA priority (0..3|lowest..highest).
-* @note The priority level is used for both the TX and RX DMA streams but
-* because of the streams ordering the RX stream has always priority
-* over the TX stream.
-*/
-#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C1_DMA_PRIORITY 1
-#endif
-
-/**
-* @brief I2C2 DMA priority (0..3|lowest..highest).
-* @note The priority level is used for both the TX and RX DMA streams but
-* because of the streams ordering the RX stream has always priority
-* over the TX stream.
-*/
-#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C2_DMA_PRIORITY 1
-#endif
-
-/**
-* @brief I2C3 DMA priority (0..3|lowest..highest).
-* @note The priority level is used for both the TX and RX DMA streams but
-* because of the streams ordering the RX stream has always priority
-* over the TX stream.
-*/
-#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C3_DMA_PRIORITY 1
-#endif
-
-/**
- * @brief I2C DMA error hook.
- * @note The default action for DMA errors is a system halt because DMA
- * error can only happen because programming errors.
- */
-#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
-#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
-#endif
-
-#if STM32_ADVANCED_DMA || defined(__DOXYGEN__)
-
-/**
- * @brief DMA stream used for I2C1 RX operations.
- * @note This option is only available on platforms with enhanced DMA.
- */
-#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
-#endif
-
-/**
- * @brief DMA stream used for I2C1 TX operations.
- * @note This option is only available on platforms with enhanced DMA.
- */
-#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
-#endif
-
-/**
- * @brief DMA stream used for I2C2 RX operations.
- * @note This option is only available on platforms with enhanced DMA.
- */
-#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
-#endif
-
-/**
- * @brief DMA stream used for I2C2 TX operations.
- * @note This option is only available on platforms with enhanced DMA.
- */
-#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
-#endif
-
-/**
- * @brief DMA stream used for I2C3 RX operations.
- * @note This option is only available on platforms with enhanced DMA.
- */
-#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
-#endif
-
-/**
- * @brief DMA stream used for I2C3 TX operations.
- * @note This option is only available on platforms with enhanced DMA.
- */
-#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
-#endif
-
-#else /* !STM32_ADVANCED_DMA */
-
-/* Fixed streams for platforms using the old DMA peripheral, the values are
- valid for both STM32F1xx and STM32L1xx.*/
-#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
-#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
-#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
-#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
-
-#endif /* !STM32_ADVANCED_DMA*/
-
-/* Flag for the whole STM32F1XX family. */
-#if defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \
- defined(STM32F10X_HD_VL) || defined(STM32F10X_LD) || \
- defined(STM32F10X_MD) || defined(STM32F10X_HD) || \
- defined(STM32F10X_XL) || defined(STM32F10X_CL)
-#define STM32F1XX_I2C
-#endif
-/** @} */
-
-/*===========================================================================*/
-/* Derived constants and error checks. */
-/*===========================================================================*/
-
-/** @brief error checks */
-#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1
-#error "I2C1 not present in the selected device"
-#endif
-
-#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2
-#error "I2C2 not present in the selected device"
-#endif
-
-#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3
-#error "I2C3 not present in the selected device"
-#endif
-
-#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && \
- !STM32_I2C_USE_I2C3
-#error "I2C driver activated but no I2C peripheral assigned"
-#endif
-
-#if STM32_I2C_USE_I2C1 && \
- !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY)
-#error "Invalid IRQ priority assigned to I2C1"
-#endif
-
-#if STM32_I2C_USE_I2C2 && \
- !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY)
-#error "Invalid IRQ priority assigned to I2C2"
-#endif
-
-#if STM32_I2C_USE_I2C3 && \
- !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY)
-#error "Invalid IRQ priority assigned to I2C3"
-#endif
-
-#if STM32_I2C_USE_I2C1 && \
- !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY)
-#error "Invalid DMA priority assigned to I2C1"
-#endif
-
-#if STM32_I2C_USE_I2C2 && \
- !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY)
-#error "Invalid DMA priority assigned to I2C2"
-#endif
-
-#if STM32_I2C_USE_I2C3 && \
- !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY)
-#error "Invalid DMA priority assigned to I2C3"
-#endif
-
-/* The following checks are only required when there is a DMA able to
- reassign streams to different channels.*/
-#if STM32_ADVANCED_DMA
-/* Check on the presence of the DMA streams settings in mcuconf.h.*/
-#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \
- !defined(STM32_I2C_I2C1_TX_DMA_STREAM))
-#error "I2C1 DMA streams not defined"
-#endif
-
-#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \
- !defined(STM32_I2C_I2C2_TX_DMA_STREAM))
-#error "I2C2 DMA streams not defined"
-#endif
-
-/* Check on the validity of the assigned DMA channels.*/
-#if STM32_I2C_USE_I2C1 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \
- STM32_I2C1_RX_DMA_MSK)
-#error "invalid DMA stream associated to I2C1 RX"
-#endif
-
-#if STM32_I2C_USE_I2C1 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \
- STM32_I2C1_TX_DMA_MSK)
-#error "invalid DMA stream associated to I2C1 TX"
-#endif
-
-#if STM32_I2C_USE_I2C2 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \
- STM32_I2C2_RX_DMA_MSK)
-#error "invalid DMA stream associated to I2C2 RX"
-#endif
-
-#if STM32_I2C_USE_I2C2 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \
- STM32_I2C2_TX_DMA_MSK)
-#error "invalid DMA stream associated to I2C2 TX"
-#endif
-
-#if STM32_I2C_USE_I2C3 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \
- STM32_I2C3_RX_DMA_MSK)
-#error "invalid DMA stream associated to I2C3 RX"
-#endif
-
-#if STM32_I2C_USE_I2C3 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \
- STM32_I2C3_TX_DMA_MSK)
-#error "invalid DMA stream associated to I2C3 TX"
-#endif
-#endif /* STM32_ADVANCED_DMA */
-
-#if !defined(STM32_DMA_REQUIRED)
-#define STM32_DMA_REQUIRED
-#endif
-
-/* Check clock range. */
-#if defined(STM32F4XX)
-#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 42)
-#error "I2C peripheral clock frequency out of range."
-#endif
-
-#elif defined(STM32L1XX)
-#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 32)
-#error "I2C peripheral clock frequency out of range."
-#endif
-
-#elif defined(STM32F2XX)
-#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 30)
-#error "I2C peripheral clock frequency out of range."
-#endif
-
-#elif defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \
- defined(STM32F10X_HD_VL)
-#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 24)
-#error "I2C peripheral clock frequency out of range."
-#endif
-
-#elif defined(STM32F10X_LD) || defined(STM32F10X_MD) || \
- defined(STM32F10X_HD) || defined(STM32F10X_XL) || \
- defined(STM32F10X_CL)
-#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 36)
-#error "I2C peripheral clock frequency out of range."
-#endif
-#else
-#error "unspecified, unsupported or invalid STM32 platform"
-#endif
-
-/*===========================================================================*/
-/* Driver data structures and types. */
-/*===========================================================================*/
-
-/**
- * @brief Type representing an I2C address.
- */
-typedef uint16_t i2caddr_t;
-
-/**
- * @brief Type of I2C driver condition flags.
- */
-typedef uint32_t i2cflags_t;
-
-/**
- * @brief Supported modes for the I2C bus.
- */
-typedef enum {
- OPMODE_I2C = 1,
- OPMODE_SMBUS_DEVICE = 2,
- OPMODE_SMBUS_HOST = 3,
-} i2copmode_t;
-
-/**
- * @brief Supported duty cycle modes for the I2C bus.
- */
-typedef enum {
- STD_DUTY_CYCLE = 1,
- FAST_DUTY_CYCLE_2 = 2,
- FAST_DUTY_CYCLE_16_9 = 3,
-} i2cdutycycle_t;
-
-/**
- * @brief Type of a structure representing an I2C driver.
- */
-typedef struct I2CDriver I2CDriver;
-
-/**
- * @brief Driver configuration structure.
- */
-typedef struct {
- i2copmode_t op_mode; /**< @brief Specifies the I2C mode. */
- uint32_t clock_speed; /**< @brief Specifies the clock frequency.
- @note Must be set to a value lower
- than 400kHz. */
- i2cdutycycle_t duty_cycle; /**< @brief Specifies the I2C fast mode
- duty cycle. */
-#if HAL_USE_I2C_STARTFIX && HAL_USE_I2C_SLAVE
- void (*armStartDetect)(void); /**< @brief Arm Start Condition Detector */
- void (*disarmStartDetect)(void);/**< @brief Disarm Start Condition Detector */
-#endif
-} I2CConfig;
-
-
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
-
-typedef struct I2CSlaveMsg I2CSlaveMsg;
-
-/*
- returns the current I2C slave message receive configuration
-*/
-I2CSlaveMsg *i2cSlaveGetReceiveMsg(I2CDriver *i2cp);
-
-
-/*
- returns the current I2C slave message reply configuration
-*/
-I2CSlaveMsg *i2cSlaveGetReplyMsg(I2CDriver *i2cp);
-
-
-/*
- I2C Slave Message Call Back.
- Invoked from interrupt context just after
- the last byte of the message is transferred or slaveAdr is matched.
-
- Use i2cSlaveReceiveMsg() or i2cSlaveReplyMsg() to access
- the relevant message handling configuration
-*/
-typedef void I2CSlaveMsgCB(I2CDriver *i2cp);
-
-
-/*
- I2CSlaveMsg message handling configurations are normally
- stored in read-only memory.
- They describe either a buffer to contain incoming messages from
- a bus master and associated callback functions, or one
- preloaded with an outgoing reply to a read request and its callbacks.
-*/
-
-struct I2CSlaveMsg {
- size_t size; /* sizeof(body) -- zero if master must wait */
- uint8_t *body; /* message contents -- or NULL if master must wait */
- I2CSlaveMsgCB *adrMatched; /* invoked when slave address matches */
- I2CSlaveMsgCB *processMsg; /* invoked after message is transferred */
- I2CSlaveMsgCB *exception; /* invoked if error or timeout during transfer */
-};
-
-
-I2CSlaveMsgCB I2CSlaveDummyCB;
-/*
- dummy callback -- placeholder to ignore event
-*/
-
- /* lock bus on receive or reply -- force master to wait */
-extern const I2CSlaveMsg I2CSlaveLockOnMsg;
-
-#endif /* HAL_USE_I2C_SLAVE */
-
-
-/**
- * @brief Structure representing an I2C driver.
- */
-struct I2CDriver {
- /**
- * @brief Driver state.
- */
- i2cstate_t state;
- /**
- * @brief Current configuration data.
- */
- const I2CConfig *config;
- /**
- * @brief Error flags.
- */
- i2cflags_t errors;
-#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
-#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__)
- /**
- * @brief Mutex protecting the bus.
- */
- mutex_t mutex;
-#elif CH_CFG_USE_SEMAPHORES
- semaphore_t semaphore;
-#endif
-#endif /* I2C_USE_MUTUAL_EXCLUSION */
-#if defined(I2C_DRIVER_EXT_FIELDS)
- I2C_DRIVER_EXT_FIELDS
-#endif
- /* End of the mandatory fields.*/
- /**
- * @brief Thread waiting for I/O completion.
- */
- thread_reference_t thread;
- /**
- * @brief Current slave address without R/W bit.
- */
- i2caddr_t addr;
- /**
- * @brief Master RX DMA buffer size.
- */
- uint16_t masterRxbytes;
- /**
- * @brief Master TX DMA buffer size.
- */
- uint16_t masterTxbytes;
- /**
- * @brief Master RX DMA buffer base.
- */
- uint8_t *masterRxbuf;
- /**
- * @brief Master TX DMA buffer base.
- */
- const uint8_t *masterTxbuf;
- /**
- * @brief RX DMA mode bit mask.
- */
- uint32_t rxdmamode;
- /**
- * @brief TX DMA mode bit mask.
- */
- uint32_t txdmamode;
- /**
- * @brief Receive DMA channel.
- */
- const stm32_dma_stream_t *dmarx;
- /**
- * @brief Transmit DMA channel.
- */
- const stm32_dma_stream_t *dmatx;
- /**
- * @brief Pointer to the I2Cx registers block.
- */
- I2C_TypeDef *i2c;
-
- /**
- * @brief low level I2C interface / protocol state
- */
- enum i2cMode {
- i2cIdle=1, /* awaiting address or inactive */
- i2cSlaveRxing, /* receiving message */
- i2cLockedRxing, /* stretching clock before receiving message */
- i2cSlaveReplying, /* replying to query */
- i2cLockedReplying, /* stretching clock before replying to query */
-
- i2cIsMaster=0x11, /* sent start bit (mastering bus) */
- i2cMasterStarted, /* repeated start after write */
- i2cMasterSelecting, /* sending slave address */
- i2cMasterRxing, /* receiving reply from slave */
- i2cMasterTxing /* sending message to slave */
- } mode;
-
-#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE
- /**
- * @brief I2C transaction timer
- */
- virtual_timer_t timer;
-#endif
-#if HAL_USE_I2C_LOCK
- /**
- * @brief I2C bus lock duration
- */
- systime_t lockDuration;
-#endif
-#if HAL_USE_I2C_SLAVE
- /* additional fields to support I2C slave transactions */
-
- /**
- * @brief slave address of message being processed
- */
- i2caddr_t targetAdr;
- /**
- * @brief Error Mask for last slave message
- */
- i2cflags_t slaveErrors;
- /**
- * @brief Length of most recently transferred slave message
- */
- uint32_t slaveBytes;
- /**
- * @brief Maximum # of ticks slave may stretch the I2C clock
- */
- systime_t slaveTimeout;
- /**
- * @brief Pointer to slave message reception handler
- */
- const I2CSlaveMsg *slaveRx;
- /**
- * @brief Pointer to slave message Reply handler
- */
- const I2CSlaveMsg *slaveReply;
- /**
- * @brief Pointer to handler for next slave received message
- */
- const I2CSlaveMsg *slaveNextRx;
- /**
- * @brief Pointer to handler for next slave reply message
- */
- const I2CSlaveMsg *slaveNextReply;
-#endif
-};
-
-/*===========================================================================*/
-/* Driver macros. */
-/*===========================================================================*/
-
-/**
- * @brief Get errors from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
-
-
-#if HAL_USE_I2C_LOCK
-/**
- * @brief Unlock I2C bus after the end of the next transaction
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- **/
-#define i2c_lld_unlock(i2cp) (i2cp->lockDuration = TIME_IMMEDIATE)
-#endif
-
-
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
-/**
- * @brief Get slave errors from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveErrors(i2cp) ((i2cp)->slaveErrors)
-
-/**
- * @brief Get slave message bytes transferred from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveBytes(i2cp) ((i2cp)->slaveBytes)
-
-
-/**
- * @brief Get slave timeout in ticks from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveTimeout(i2cp) ((i2cp)->slaveTimeout)
-
-/**
- * @brief Set slave timeout in ticks for I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_set_slaveTimeout(i2cp,ticks) ((i2cp)->slaveTimeout=(ticks))
-
-/**
- * @brief Get slave target address from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveTargetAdr(i2cp) ((i2cp)->targetAdr)
-
-/**
- * @brief Get slave receive message descriptor from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveReceive(i2cp) ((i2cp)->slaveNextRx)
-
-/**
- * @brief Get slave reply message descriptor from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveReply(i2cp) ((i2cp)->slaveNextReply)
-
-#endif
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-#if !defined(__DOXYGEN__)
-#if STM32_I2C_USE_I2C1
-extern I2CDriver I2CD1;
-#endif
-
-#if STM32_I2C_USE_I2C2
-extern I2CDriver I2CD2;
-#endif
-
-#if STM32_I2C_USE_I2C3
-extern I2CDriver I2CD3;
-#endif
-#endif /* !defined(__DOXYGEN__) */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
- void i2c_lld_init(void);
- void i2c_lld_start(I2CDriver *i2cp);
- void i2c_lld_stop(I2CDriver *i2cp);
- msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
- const uint8_t *txbuf, size_t txbytes,
- uint8_t *rxbuf, size_t rxbytes,
- systime_t timeout);
- msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
- uint8_t *rxbuf, size_t rxbytes,
- systime_t timeout);
-
-#if HAL_USE_I2C_LOCK /* I2C slave mode support */
- void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration);
-#endif
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
- msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr);
- void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr);
- void i2c_lld_unmatchAll(I2CDriver *i2cp);
- void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg);
- void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg);
-#if HAL_USE_I2C_STARTFIX
- void i2c_lld_startDetected(I2CDriver *i2cp);
- void i2c_lld_noStartDetector(void);
-#define i2cNoStartDetector i2c_lld_noStartDetector
-#endif
-#endif /* HAL_USE_I2C_SLAVE */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HAL_USE_I2C */
-
-#endif /* _I2C_LLD_H_ */
-
-/** @} */
diff --git a/drivers/chibios/i2cslave/I2Cv2/driver.mk b/drivers/chibios/i2cslave/I2Cv2/driver.mk
deleted file mode 100644
index 06fb82ff8f..0000000000
--- a/drivers/chibios/i2cslave/I2Cv2/driver.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-ifeq ($(USE_HAL_I2C_FALLBACK),yes)
- # Fallback SW driver.
- ifeq ($(USE_SMART_BUILD),yes)
- ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
- PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
- endif
- else
- PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
- endif
- PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C
-else
- # Default HW driver.
- ifeq ($(USE_SMART_BUILD),yes)
- ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
- PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c
- endif
- else
- PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c
- endif
- PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2
-endif
diff --git a/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c b/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c
deleted file mode 100644
index b6df7c7169..0000000000
--- a/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c
+++ /dev/null
@@ -1,2065 +0,0 @@
-/*
- ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-/*
-TODO:
-1. Make sure slave mode registers updated OK
-2. Test what of the newly inserted defines etc is actually necessary
-3. Check whether all relevant features available on all ports on all processors (they are on F7, F051)
-4. Do we need timer to get involved on master mode transactions? (May be multimaster requirement)
-5. What about multimaster? Possibly nothing special to do, other than support all transitions round master and slave modes.
-(Manual: "By default, it operates in slave mode. The interface automatically switches from slave to
-master when it generates a START condition, and from master to slave if an arbitration loss
-or a STOP generation occurs, allowing multimaster capability")
-6. Understand use of lock timer - may only be relevant for multimaster, or even unnecessary
-7. Check slave transfers > 255 bytes
-
-NOTES:
-1. 10-bit addressing, masking options not currently supported in software in slave mode
- (OAR1 hardware supports single 10-bit address matching; OAR2 supports 7-bit addressing with mask)
-2. Address zero supported by setting 'General Call' flag in CR1 in slave mode (set with call to match address zero)
-3. Clock stretching always enabled
-4. Relevant configurable bits in CR1:
- ANFOFF (analog noise filter)
- DNF (digital noise filter bits)
-5. Setting STM32_I2C_DEBUG_ENABLE to TRUE logs various events into a short circular buffer, which can then be examined using
-the debugger. Alternatively, a call to i2cPrintQ(BaseSequentialStream *chp) prints the buffer. Note that the buffer only
-has a write pointer, so once full its necessary to infer the start and end of the data
-
- */
-
-/**
- * @file STM32/I2Cv2/i2c_lld.c
- * @brief STM32 I2C subsystem low level driver source.
- *
- * @addtogroup I2C
- * @{
- */
-
-#include "hal.h"
-
-#if HAL_USE_I2C || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver local definitions. */
-/*===========================================================================*/
-
-#if STM32_I2C_USE_DMA == TRUE
-#define DMAMODE_COMMON \
- (STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | \
- STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | \
- STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE)
-
-#define I2C1_RX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \
- STM32_I2C1_RX_DMA_CHN)
-
-#define I2C1_TX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \
- STM32_I2C1_TX_DMA_CHN)
-
-#define I2C2_RX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \
- STM32_I2C2_RX_DMA_CHN)
-
-#define I2C2_TX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \
- STM32_I2C2_TX_DMA_CHN)
-
-#define I2C3_RX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \
- STM32_I2C3_RX_DMA_CHN)
-
-#define I2C3_TX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \
- STM32_I2C3_TX_DMA_CHN)
-
-#define I2C4_RX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_RX_DMA_STREAM, \
- STM32_I2C4_RX_DMA_CHN)
-
-#define I2C4_TX_DMA_CHANNEL \
- STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_TX_DMA_STREAM, \
- STM32_I2C4_TX_DMA_CHN)
-#endif /* STM32_I2C_USE_DMA == TRUE */
-
-#if STM32_I2C_USE_DMA == TRUE
-#define i2c_lld_get_rxbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmarx)
-#define i2c_lld_get_txbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmatx)
-#else
-#define i2c_lld_get_rxbytes(i2cp) (i2cp)->rxbytes
-#define i2c_lld_get_txbytes(i2cp) (i2cp)->txbytes
-#endif
-
-/*===========================================================================*/
-/* Driver constants. */
-/*===========================================================================*/
-#define I2C_ERROR_MASK \
- ((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \
- I2C_ISR_TIMEOUT | I2C_ISR_ALERT))
-
-#define I2C_INT_MASK \
- ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \
- I2C_ISR_ADDR | I2C_ISR_RXNE | I2C_ISR_TXIS))
-
-/* Mask of interrupt bits cleared automatically - we mustn't clear ADDR else clock stretching doesn't happen */
-#define I2C_INT_CLEAR_MASK \
- ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \
- I2C_ISR_RXNE | I2C_ISR_TXIS))
-
-
-/*===========================================================================*/
-/* Driver exported variables. */
-/*===========================================================================*/
-
-/** @brief I2C1 driver identifier.*/
-#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__)
-I2CDriver I2CD1;
-#endif
-
-/** @brief I2C2 driver identifier.*/
-#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__)
-I2CDriver I2CD2;
-#endif
-
-/** @brief I2C3 driver identifier.*/
-#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__)
-I2CDriver I2CD3;
-#endif
-
-/** @brief I2C4 driver identifier.*/
-#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__)
-I2CDriver I2CD4;
-#endif
-
-/*===========================================================================*/
-/* Driver local variables and types. */
-/*===========================================================================*/
-
-#if STM32_I2C_DEBUG_ENABLE
-/*
- * Quick and dirty queue to record event interrupts (useful for debug)
- *
- * Assigned codes (may be others not noted here):
- * 0x02 - NAK received
- * 0x03 - transfer complete received
- * 0x04 - Address match (records current mode before any error recovery etc)
- * 0x05 - STOP received
- * 0x06 - Part transfer complete interrupt
- * 0x07 - Recovery from untidily finished previous transaction
- * 0x08 - Recovery from untidily finished previous transaction
- * 0x09 - Recovery from untidily finished previous transaction
- * 0x10 - error in slave address match - send
- * 0x11 - error in slave address match - receive
- * 0x12 - address match - send
- * 0x13 - address match - receive
- * 0x14 - start slave receive operation
- * 0x15 - lock on pending slave receive operation (no buffer)
- * 0x16 - start slave transmit operation
- * 0x17 - lock on pending slave transmit operation (no buffer available)
- * 0x80 - new reply set
- * 0x81 - reply used immediately
- * 0x82 - new receive buffer set
- * 0x83 - receive buffer used immediately
- * 0xcc - clearing down after transmission - triggered by NAK received (usually valid)
- * 0xd0 - Slave error being signalled
- * 0xd1 - Slave error due to timeout
-*/
-#define QEVENTS 32
-
-typedef struct i2cQ_t {
- uint8_t code;
- uint8_t state; // Channel state
- uint8_t mode; // Mode (mostly for slave)
- uint16_t param; // Parameter sometimes used
-} i2cQ_t;
-i2cQ_t i2cQ[QEVENTS];
-unsigned i2cI = QEVENTS;
-#define qEvt(posn,info) {if (++i2cI >= QEVENTS) i2cI = 0; \
- i2cQ[i2cI].code=(posn); i2cQ[i2cI].state=(i2cp->state); i2cQ[i2cI].mode=(i2cp->mode); i2cQ[i2cI].param=(info); }
-
-#include "chprintf.h"
-
-void i2cPrintQ(BaseSequentialStream *chp)
-{
- uint8_t i;
- if (QEVENTS == 0)
- {
- chprintf(chp, "I2C Debug queue disabled\r\n");
- }
- else
- {
- chprintf(chp, "I2C debug ring - write pointer currently %02d\r\n", i2cI);
- }
- for (i = 0; i < QEVENTS; i++)
- {
- chprintf(chp, "%02d: %02x->%02x %02x %04x\r\n", i, i2cQ[i].code, i2cQ[i].state, i2cQ[i].mode, i2cQ[i].param);
- if (i2cQ[i].code == 0) break; // Handle partially filled queue
- }
-}
-
-#else
-#define qEvt(posn,info)
-#endif
-
-
-
-
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
-
-
-void I2CSlaveDummyCB(I2CDriver *i2cp)
-/*
- dummy callback -- placeholder to ignore event
-*/
-{(void)i2cp;}
-
- /* lock bus on receive or reply message */
-const I2CSlaveMsg I2CSlaveLockOnMsg = {
- 0, NULL, I2CSlaveDummyCB, I2CSlaveDummyCB, I2CSlaveDummyCB
-};
-
-#endif
-
-/*===========================================================================*/
-/* Driver local functions. */
-/*===========================================================================*/
-
-#if HAL_USE_I2C_MASTER
-/**
- * @brief Slave (remote) address setup in master mode.
- * @note The RW bit is set to zero internally.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] addr slave device address
- *
- * @notapi
- */
-static void i2c_lld_set_address(I2CDriver *i2cp, i2caddr_t addr) {
- I2C_TypeDef *dp = i2cp->i2c;
-
- /* Address alignment depends on the addressing mode selected.*/
- if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0U)
- dp->CR2 = (uint32_t)addr << 1U;
- else
- dp->CR2 = (uint32_t)addr;
-}
-#endif
-
-
-
-/**
- * @brief I2C RX transfer setup.
- * @note Configures transfer count and related flags
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void i2c_lld_setup_rx_transfer(I2CDriver *i2cp) {
- I2C_TypeDef *dp = i2cp->i2c;
- uint32_t reload;
- size_t n;
-
- /* The unit can transfer 255 bytes maximum in a single operation (device constraint). */
-#if STM32_I2C_USE_DMA
- if (i2cp->config->rxchar_cb)
- {
- n = i2cp->rxbytes; // Always interrupt-driven if we have a receive callback
- }
- else
- {
- n = i2c_lld_get_rxbytes(i2cp); // Otherwise get length from DMA or counter as appropriate
- }
-#else
- n = i2cp->rxbytes;
-#endif
- if (n > 255U) {
- n = 255U;
- reload = I2C_CR2_RELOAD;
- }
- else {
- reload = 0U;
- }
-
- /* Configures the CR2 registers with both the calculated and static
- settings. (Nothing much relevant in static settings - just PEC for SMBUS? */
- dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | I2C_CR2_RD_WRN |
- (n << 16U) | reload;
-}
-
-
-
-/**
- * @brief I2C TX transfer setup.
- * @note Configures transfer count and related flags
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void i2c_lld_setup_tx_transfer(I2CDriver *i2cp) {
- I2C_TypeDef *dp = i2cp->i2c;
- uint32_t reload;
- size_t n;
-
- /* The unit can transfer 255 bytes maximum in a single operation. */
- n = i2c_lld_get_txbytes(i2cp); // Get transaction size from DMA or buffer as configured
- if (n > 255U) {
- n = 255U;
- reload = I2C_CR2_RELOAD;
- }
- else {
- reload = 0U;
- }
-
- /* Configures the CR2 registers with both the calculated and static
- settings.*/
- dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 |
- (n << 16U) | reload;
-}
-
-
-
-/**
- * @brief Aborts an I2C transaction.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void i2c_lld_abort_operation(I2CDriver *i2cp) {
- I2C_TypeDef *dp = i2cp->i2c;
-
-// Note: clearing PE doesn't affect configuration bits (including slave addresses)
- if (dp->CR1 & I2C_CR1_PE) {
- /* Stops the I2C peripheral.*/
- dp->CR1 &= ~I2C_CR1_PE;
- while (dp->CR1 & I2C_CR1_PE)
- dp->CR1 &= ~I2C_CR1_PE;
- dp->CR1 |= I2C_CR1_PE;
- }
-
-#if STM32_I2C_USE_DMA == TRUE
- /* Stops the associated DMA streams.*/
- dmaStreamDisable(i2cp->dmatx);
- dmaStreamDisable(i2cp->dmarx);
-#else
- dp->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); // Stop byte-orientated interrupts
-#endif
-}
-
-
-
-#if HAL_USE_I2C_SLAVE || HAL_USE_I2C_LOCK
-/**
- * @brief stop transaction timeout countdown
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static inline void stopTimer(I2CDriver *i2cp)
-{
- osalSysLockFromISR();
- chVTResetI(&i2cp->timer);
- osalSysUnlockFromISR();
-}
-#else
-#define stopTimer(ignored) {}
-#endif
-
-
-
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
-
-/**
- * @brief report error via slave exception callback
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @note moves back to the idle mode
- * @notapi
- */
-static inline void reportSlaveError(I2CDriver *i2cp) {
- if (i2cp->mode >= i2cIsMaster) return;
- qEvt(0xd0, i2cp->slaveErrors);
- const I2CSlaveMsg *xfer = i2cp->mode >= i2cSlaveReplying ?
- i2cp->slaveReply : i2cp->slaveRx;
- if (xfer->exception)
- xfer->exception(i2cp);
- i2cp->mode = i2cIdle;
- i2cp->targetAdr = i2cInvalidAdr;
-}
-
-
-/**
- * @brief Handling of stalled slave mode I2C transactions - timer handler.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void slaveTimeExpired(void *i2cv) {
- I2CDriver *i2cp = i2cv;
-
- if (i2cp->mode < i2cIsMaster)
- {
- i2c_lld_abort_operation(i2cp);
- reportSlaveError(i2cp);
- qEvt(0xd1, 0);
- }
-}
-
-
-/**
- * @brief start or restart slave mode transaction
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] targetAdr slave address which was matched
- *
- * @notapi
- */
-static inline void i2cStartSlaveAction(I2CDriver *i2cp, i2caddr_t targetAdr)
-{
- stopTimer(i2cp);
- i2cp->targetAdr = targetAdr;
- i2cp->slaveBytes = 0;
- i2cp->slaveErrors = 0;
- if (i2cp->slaveTimeout != TIME_INFINITE)
- {
- osalSysLockFromISR();
- chVTSetI(&i2cp->timer, i2cp->slaveTimeout, slaveTimeExpired, i2cp);
- osalSysUnlockFromISR();
- }
-}
-
-
-/**
- * @brief end slave receive message DMA
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static inline void i2cEndSlaveRxDMA(I2CDriver *i2cp)
-{
- size_t bytesRemaining = i2c_lld_get_rxbytes(i2cp);
- if (i2cp->slaveBytes)
- i2cp->slaveBytes += 0xffff - bytesRemaining;
- else
- i2cp->slaveBytes = i2cp->slaveRx->size - bytesRemaining;
-#if STM32_I2C_USE_DMA == TRUE
- /* Disabling RX DMA channel.*/
- dmaStreamDisable(i2cp->dmarx);
-#else
- i2cp->i2c->CR1 &= ~(I2C_CR1_RXIE);
-#endif
-}
-
-
-
-/**
- * @brief end slave transmit DMA
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] bytesRemaining bytes lost in output queue
- *
- * @notapi
- */
-static inline void i2cEndSlaveTxDMA(I2CDriver *i2cp, size_t bytesRemaining)
-{
- bytesRemaining += i2c_lld_get_rxbytes(i2cp);
- if (i2cp->slaveBytes)
- i2cp->slaveBytes += 0xffff - bytesRemaining;
- else
- i2cp->slaveBytes = i2cp->slaveReply->size - bytesRemaining;
-#if STM32_I2C_USE_DMA == TRUE
- /* Disabling TX DMA channel.*/
- dmaStreamDisable(i2cp->dmatx);
-#else
- i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE);
-#endif
-}
-
-#endif
-
-
-
-
-/**
- * @brief Start a receive transaction (by enabling DMA, or enabling Rx character interrupts)
- *
- * @note All registers etc must be set up first
- */
-static inline void i2cStartReceive(I2CDriver *i2cp)
-{
-#if STM32_I2C_USE_DMA == TRUE
- if (i2cp->config->rxchar_cb)
- {
- // Callback in use - use interrupt-driven transfer
- i2cp->i2c->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE;
- }
- else
- {
- /* Enabling RX DMA.*/
- dmaStreamEnable(i2cp->dmarx);
-
- /* Transfer complete interrupt enabled.*/
- i2cp->i2c->CR1 |= I2C_CR1_TCIE;
- }
-#else
-
- /* Transfer complete and RX interrupts enabled.*/
- i2cp->i2c->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE;
-#endif
-}
-
-
-/**
- * @brief Disable transmit data transfer, whether DMA or interrupt-driven
- */
-static inline void i2cDisableTransmitOperation(I2CDriver *i2cp)
-{
-#if STM32_I2C_USE_DMA == TRUE
- /* Disabling TX DMA channel.*/
- dmaStreamDisable(i2cp->dmatx);
-#else
- i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE);
-#endif
-}
-
-
-/**
- * @brief Disable receive data transfer, whether DMA or interrupt-driven
- */
-static inline void i2cDisableReceiveOperation(I2CDriver *i2cp)
-{
-#if STM32_I2C_USE_DMA == TRUE
- /* Disabling RX DMA channel.*/
- dmaStreamDisable(i2cp->dmarx);
-#else
- i2cp->i2c->CR1 &= ~(I2C_CR1_RXIE);
-#endif
-}
-
-
-
-/*===========================================================================*/
-/* Shared ISR Code */
-/*===========================================================================*/
-
-/**
- * @brief I2C shared ISR code - 'Normal' (non-error) interrupts.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] isr content of the ISR register to be decoded (no masking applied)
- *
- * @notapi
- */
-static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) {
- I2C_TypeDef *dp = i2cp->i2c;
-
- /* Check for received NACK, the transfer is aborted. Do this in all modes */
- if ((isr & I2C_ISR_NACKF) != 0U)
- {
- qEvt(2, 0);
-
- i2cDisableReceiveOperation(i2cp);
- i2cDisableTransmitOperation(i2cp);
- #if HAL_USE_I2C_SLAVE
- /* NACK of last byte transmitted in slave response is NORMAL -- not an error! */
- if (i2cp->mode == i2cSlaveReplying)
- {
- qEvt(0xcc,0);
- i2cEndSlaveTxDMA(i2cp, 1);
- if (i2cp->slaveReply->processMsg)
- i2cp->slaveReply->processMsg(i2cp);
- i2cp->targetAdr = i2cInvalidAdr;
- stopTimer(i2cp);
- return;
- }
- #endif
-
- /* Error flag.*/
- i2cp->errors |= I2C_ACK_FAILURE;
-
- /* Transaction finished, send the STOP. */
- dp->CR2 |= I2C_CR2_STOP;
-
- /* Make sure no more interrupts.*/
- dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_STOPIE);
-
- if (i2cp->mode < i2cIsMaster)
- {
- i2cp->mode = i2cIdle;
- }
- else
- {
- /* Master mode - Errors are signalled to the upper layer.*/
- i2cp->mode = i2cIdle;
- // Must only wake up thread in master mode.
- _i2c_wakeup_isr(i2cp); // This is a normal completion
- }
-
- return;
- }
-
-
-#if STM32_I2C_USE_DMA == FALSE
- /* Handling of data transfer if the DMA mode is disabled - done character by character. Mode should be irrelevant */
- {
- uint32_t cr1 = dp->CR1;
-
- if ((i2cp->state == I2C_ACTIVE_TX) || (i2cp->mode == i2cSlaveReplying))
- {
- /* Transmission phase.*/
- if (((cr1 &I2C_CR1_TXIE) != 0U) && ((isr & I2C_ISR_TXIS) != 0U)) {
- dp->TXDR = (uint32_t)*i2cp->txptr;
- i2cp->txptr++;
- i2cp->txbytes--;
- if (i2cp->txbytes == 0U) {
- dp->CR1 &= ~I2C_CR1_TXIE; // Last byte sent - stop Tx interrupt
- }
- }
- }
- else
- {
- /* Receive phase.*/
- if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) {
- uint8_t c;
- *i2cp->rxptr = c = (uint8_t)dp->RXDR;
- i2cp->rxptr++;
- i2cp->rxbytes--;
- if (i2cp->config->rxchar_cb)
- {
- if (i2cp->config->rxchar_cb(i2cp, c) > 0)
- {
- /* Transaction finished, send the STOP. */
- dp->CR2 |= I2C_CR2_STOP;
-
- /* Make sure no more interrupts.*/
- dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_STOPIE);
-
- if (i2cp->mode < i2cIsMaster)
- {
- i2cp->mode = i2cIdle;
- }
- else
- {
- /* Master mode - Errors are signalled to the upper layer.*/
- i2cp->mode = i2cIdle;
- // Must only wake up thread in master mode.
- _i2c_wakeup_isr(i2cp); // This is a normal completion
- }
-
- return;
- }
- }
- if (i2cp->rxbytes == 0U) {
- dp->CR1 &= ~I2C_CR1_RXIE; // Buffer full - stop reception (TODO: Should we send NAK?? Only possible in slave mode)
- }
- }
- }
- }
-#else
- /* Receive character phase with callback enabled. */
- if ((i2cp->state == I2C_ACTIVE_RX) || (i2cp->mode == i2cMasterRxing))
- {
- uint32_t cr1 = dp->CR1;
- if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) {
- uint8_t c;
- c = (uint8_t)dp->RXDR;
- *i2cp->rxptr = c;
- i2cp->rxptr++;
- i2cp->rxbytes--;
- if (i2cp->config->rxchar_cb)
- {
- if (i2cp->config->rxchar_cb(i2cp, c) > 0)
- {
- /* Transaction finished, send the STOP. */
- dp->CR2 |= I2C_CR2_STOP;
-
- /* Make sure no more interrupts.*/
- dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_STOPIE);
-
- if (i2cp->mode < i2cIsMaster)
- {
- i2cp->mode = i2cIdle;
- }
- else
- {
- /* Master mode - Errors are signalled to the upper layer.*/
- i2cp->mode = i2cIdle;
- // Must only wake up thread in master mode.
- _i2c_wakeup_isr(i2cp); // This is a normal completion
- }
-
- return;
- }
- }
- if (i2cp->rxbytes == 0U) {
- dp->CR1 &= ~I2C_CR1_RXIE; // Buffer full - stop reception (TODO: Should we send NAK?? Only possible in slave mode)
- }
- }
- }
-#endif
-
-
-
- /* Partial transfer handling, restarting the transfer and returning. */
- if ((isr & I2C_ISR_TCR) != 0U)
- {
- qEvt(0x06, 0);
- if ((i2cp->state == I2C_ACTIVE_TX) || (i2cp->mode == i2cSlaveReplying)) {
- i2c_lld_setup_tx_transfer(i2cp);
- }
- if ((i2cp->state == I2C_ACTIVE_RX) || (i2cp->mode == i2cSlaveRxing)) {
- i2c_lld_setup_rx_transfer(i2cp);
- }
- return;
- }
-
-
-
- /* The following condition is true if a transfer phase has been completed. */
- if ((isr & I2C_ISR_TC) != 0U)
- {
- qEvt(3,i2cp->state);
-#if HAL_USE_I2C_SLAVE
- switch (i2cp->mode)
- {
- case i2cLockedRxing : /* stretching clock before receiving message - Rx buffer might be full */
- case i2cLockedReplying :
- break; // TODO: Two unsupported cases to consider - maybe they can't happen
- case i2cSlaveReplying : // Must have just finished sending a reply in slave mode
- break; // Just go on to send STOP bit and tidy up
-
- case i2cSlaveRxing : // Must have just received a message - process if we can
- i2cEndSlaveRxDMA(i2cp);
- qEvt(0x20, 0);
- if (i2cp->slaveRx->processMsg)
- i2cp->slaveRx->processMsg(i2cp);
- // TODO: Should get a reply message set - if so, start to send it and return
- return; // For now, see what happens if we just return
- break;
- default : // Assume a master mode
-#endif
- if (i2cp->state == I2C_ACTIVE_TX) {
- /* End of the transmit phase.*/
-
- i2cDisableTransmitOperation(i2cp); // Disable
-
- /* Starting receive phase if necessary.*/
- if (i2c_lld_get_rxbytes(i2cp) > 0U) {
- /* Setting up the peripheral.*/
- i2c_lld_setup_rx_transfer(i2cp);
-
- #if STM32_I2C_USE_DMA == TRUE
- // If receive callback enabled, always transfer using interrupts
- if (i2cp->config->rxchar_cb)
- {
- /* RX interrupt enabled.*/
- dp->CR1 |= I2C_CR1_RXIE;
- }
- else
- {
- /* Enabling RX DMA.*/
- dmaStreamEnable(i2cp->dmarx);
- }
- #else
- /* RX interrupt enabled.*/
- dp->CR1 |= I2C_CR1_RXIE;
- #endif
-
- /* Starts the read operation.*/
- dp->CR2 |= I2C_CR2_START;
-
- /* State change.*/
- i2cp->state = I2C_ACTIVE_RX;
- i2cp->mode = i2cMasterRxing;
-
- /* Note, returning because the transaction is not over yet.*/
- return;
- }
- }
- else
- {
- /* End of the receive phase.*/
- i2cDisableReceiveOperation(i2cp);
- }
-
-#if HAL_USE_I2C_SLAVE
- }
-#endif
-
- /* Transaction finished sending the STOP. */
- dp->CR2 |= I2C_CR2_STOP;
-
- /* Make sure no more 'Transfer Complete' interrupts. */
- dp->CR1 &= ~I2C_CR1_TCIE;
-
- /* Normal transaction end.*/
- if (i2cp->mode < i2cIsMaster)
- {
- // Slave mode - just move to idle state
- i2cp->mode = i2cIdle;
- }
- else
- {
- i2cp->mode = i2cIdle;
- // Must only wake up thread in master mode
- _i2c_wakeup_isr(i2cp);
- }
- }
-
-
-#if HAL_USE_I2C_SLAVE
- uint8_t abort = 0;
- /* Check for address match - if so, we're slave */
- if ((isr & I2C_ISR_ADDR) != 0U)
- {
- i2caddr_t targetAdr = (isr & I2C_ISR_ADDCODE) >> 17; // Identify which slave address used
- uint8_t xferDir = (isr & I2C_ISR_DIR) ? 0 : 1; // Status bit is 0 for receive, 1 for transmit. xferDir inverts sense
- dp->CR1 |= I2C_CR1_STOPIE; // Enable STOP interrupt so we know when slave transaction done
-
- /* First, tidy up from previous transactions as necessary */
- qEvt(0x04, 0);
- switch (i2cp->mode) {
- case i2cIdle:
- break;
- case i2cSlaveRxing: /* Previous transaction not completed properly, or
- maybe we were sent a message without being asked for a reply */
- qEvt(0x07, 0);
- i2cEndSlaveRxDMA(i2cp);
- if (i2cp->slaveRx->processMsg)
- i2cp->slaveRx->processMsg(i2cp); // Execute callback if defined
- break;
- case i2cSlaveReplying: /* Master did not NACK last transmitted byte (most likely picked up by NAK handler) */
- qEvt(0x08, 0);
- if (!xferDir)
- {
- qEvt(0x09, 0);
- i2cEndSlaveTxDMA(i2cp, 2);
- if (i2cp->slaveReply->processMsg)
- i2cp->slaveReply->processMsg(i2cp);
- break;
- }
- // Intentionally don't break if we're addressed to receive
- default:
- // todo: Does this lot happen in the right order? Is an abort appropriate? Or should we just continue?
- qEvt(0x10 + xferDir, 0);
- i2cp->slaveErrors = I2C_UNKNOWN_ERROR + i2cp->mode;
- i2c_lld_abort_operation(i2cp); /* reset and reinit */
- stopTimer(i2cp);
- reportSlaveError(i2cp); // This clears down to idle
- abort = 1;
- }
- if (!abort)
- {
- qEvt(0x12 + xferDir, (i2cp->slaveNextRx->size));
- if (xferDir)
- {
- /* Start Receive */
- /* If receive buffer still full, need to extend clock for timeout. Otherwise set up to receive */
- dp->CR1 &= ~I2C_CR1_SBC; // Not needed with receive
- i2cStartSlaveAction(i2cp, targetAdr);
-
- const I2CSlaveMsg *rx = i2cp->slaveNextRx;
- if (rx->adrMatched) // Q: Can rx ever be NULL?
- rx->adrMatched(i2cp); // Execute callback on address match if specified
- rx = i2cp->slaveRx = i2cp->slaveNextRx; // Reload message pointer in case callback changed it
- if (rx->body && rx->size)
- {
- /* Receive buffer available - can receive immediately. Set up slave RX DMA */
- i2c_lld_setup_rx_transfer(i2cp);
- #if STM32_I2C_USE_DMA == TRUE
- /* RX DMA setup.*/
- dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
- dmaStreamSetMemory0(i2cp->dmarx, rx->body);
- dmaStreamSetTransactionSize(i2cp->dmarx, rx->size);
- #else
- i2cp->rxptr = rx->body;
- i2cp->rxbytes = rx->size;
- #endif
-
- i2cStartReceive(i2cp);
- dp->ICR = I2C_ISR_ADDR; // We can release the clock stretch now
- i2cp->mode = i2cSlaveRxing;
- qEvt(0x14,0);
- }
- else
- {
- /* No reply set up - hold clock low and wait (happens automatically) */
- qEvt(0x15,0);
- i2cp->mode = i2cLockedRxing;
- }
- }
- else
- {
- /* Start Transmit */
- i2cStartSlaveAction(i2cp, targetAdr);
- const I2CSlaveMsg *reply = i2cp->slaveNextReply;
- const I2CSlaveMsg *rx = i2cp->slaveNextRx; // Receive control block
- if (rx->adrMatched) // Q: Can rx ever be NULL?
- rx->adrMatched(i2cp); // Execute callback on address match if specified
- reply = i2cp->slaveReply = i2cp->slaveNextReply; // Reload message pointer in case callback changed it
- if (reply->body && reply->size)
- {
- /* Reply message available - can send immediately. Set up slave TX DMA */
- #if STM32_I2C_USE_DMA == TRUE
- dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
- dmaStreamSetMemory0(i2cp->dmatx, reply->body);
- dmaStreamSetTransactionSize(i2cp->dmatx, reply->size);
- /* Start transmission */
- i2c_lld_setup_tx_transfer(i2cp);
-
- /* Enabling TX DMA.*/
- dmaStreamEnable(i2cp->dmatx);
-
- /* Transfer complete interrupt enabled.*/
- dp->CR1 |= I2C_CR1_TCIE;
- #else
- /* Start transmission */
- i2cp->txptr = reply->body;
- i2cp->txbytes = reply->size;
- i2c_lld_setup_tx_transfer(i2cp);
- /* Transfer complete and TX character interrupts enabled.*/
- dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE;
- #endif
- qEvt(0x16,0);
- i2cp->mode = i2cSlaveReplying;
- dp->CR1 |= I2C_CR1_SBC; // Need this to enable byte counter in transmit mode
- dp->ICR = I2C_ISR_ADDR; // We can release the clock stretch now
- }
- else
- {
- // clock is automatically stretched if we don't clear the status bit
- //dp->CR2 &= (uint16_t)(~I2C_CR2_ITEVTEN);
- qEvt(0x17, 0);
- i2cp->mode = i2cLockedReplying;
- }
- }
- } /* if !abort */
- }
- if ((isr & I2C_ISR_STOPF) != 0U) {
- /*
- * STOP received:
- * in master mode, if generated by peripheral - can probably just ignore
- * in slave mode, if detected on bus (from any source?)
- *
- * Clear everything down - particularly relevant in slave mode
- */
- qEvt(0x05, 0);
- dp->CR1 &= ~I2C_CR1_STOPIE; // Disable STOP interrupt
- i2cDisableReceiveOperation(i2cp); // These two may not be necessary
- i2cDisableTransmitOperation(i2cp);
- stopTimer(i2cp);
- i2cp->mode = i2cIdle;
- }
-#endif
-}
-
-
-
-/**
- * @brief I2C error handler.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] isr content of the ISR register to be decoded (no masking applied)
- *
- * @notapi
- */
-static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) {
-
- i2cDisableReceiveOperation(i2cp);
- i2cDisableTransmitOperation(i2cp);
- stopTimer(i2cp);
-
-#if HAL_USE_I2C_SLAVE
- // In slave mode, just clock errors and return
- if (i2cp->mode < i2cIsMaster)
- {
- reportSlaveError(i2cp); // This clears down to idle
- return;
- }
-#endif
-
- if (isr & I2C_ISR_BERR)
- i2cp->errors |= I2C_BUS_ERROR;
-
- if (isr & I2C_ISR_ARLO)
- i2cp->errors |= I2C_ARBITRATION_LOST;
-
- if (isr & I2C_ISR_OVR)
- i2cp->errors |= I2C_OVERRUN;
-
- if (isr & I2C_ISR_TIMEOUT)
- i2cp->errors |= I2C_TIMEOUT;
-
- /* If some error has been identified then wake up the waiting thread.*/
- if (i2cp->errors != I2C_NO_ERROR)
- {
- i2cp->mode = i2cIdle;
- _i2c_wakeup_error_isr(i2cp);
- }
-}
-
-
-
-
-
-#if HAL_USE_I2C_LOCK /* I2C bus locking support */
-
-/**
- * @brief Handling of expired master bus lock timer
- *
- * @param[in] i2cv pointer to the @p I2CDriver object
- *
- * @notapi
- */
-static void lockExpired(void *i2cv) {
- I2CDriver *i2cp = i2cv;
-
- if (i2cp->mode == i2cIsMaster && !i2cp->thread) { /* between transactions */
- i2cp->i2c->CR2 |= I2C_CR2_STOP;
- i2cp->mode = i2cIdle;
- }
- i2cp->lockDuration = TIME_IMMEDIATE;
-}
-
-
-
-
-/**
- * @brief Lock I2C bus at the beginning of the next message
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] lockDuration max number of ticks to hold bus locked
- * - @a TIME_INFINITE no timeout.
- * - @a TIME_IMMEDIATE unlock the bus immediately
- * .
- *
- * Lock I2C bus at the beginning of the next message sent
- * for a maximum of lockDuration ticks. No other I2C masters will
- * be allowed to interrupt until i2cUnlock() is called.
- *
- * @notapi
- **/
-void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration)
-{
- i2cp->lockDuration = lockDuration;
- if (i2cp->mode >= i2cIsMaster) {
- stopTimer(i2cp);
- if (lockDuration == TIME_IMMEDIATE)
- lockExpired(i2cp);
- else if (lockDuration != TIME_INFINITE)
- chVTSetI(&i2cp->timer, lockDuration, lockExpired, i2cp);
- }
-}
-
-#endif
-
-/*===========================================================================*/
-/* Driver interrupt handlers. */
-/*===========================================================================*/
-
-#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__)
-#if defined(STM32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__)
-/**
- * @brief I2C1 event interrupt handler.
- *
- * @notapi
- */
-OSAL_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) {
- uint32_t isr = I2CD1.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD1.i2c->ICR = isr & ~I2C_ISR_ADDR;
-
- if (isr & I2C_ERROR_MASK)
- i2c_lld_serve_error_interrupt(&I2CD1, isr);
- else if (isr & I2C_INT_MASK)
- i2c_lld_serve_interrupt(&I2CD1, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER)
-OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) {
- uint32_t isr = I2CD1.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD1.i2c->ICR = isr & I2C_INT_CLEAR_MASK;
-
- i2c_lld_serve_interrupt(&I2CD1, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) {
- uint32_t isr = I2CD1.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD1.i2c->ICR = isr & I2C_ERROR_MASK;
-
- i2c_lld_serve_error_interrupt(&I2CD1, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-#else
-#error "I2C1 interrupt handlers not defined"
-#endif
-#endif /* STM32_I2C_USE_I2C1 */
-
-#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__)
-#if defined(STM32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__)
-/**
- * @brief I2C2 event interrupt handler.
- *
- * @notapi
- */
-OSAL_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) {
- uint32_t isr = I2CD2.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD2.i2c->ICR = isr & ~I2C_ISR_ADDR;
-
- if (isr & I2C_ERROR_MASK)
- i2c_lld_serve_error_interrupt(&I2CD2, isr);
- else if (isr & I2C_INT_MASK)
- i2c_lld_serve_interrupt(&I2CD2, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER)
-OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) {
- uint32_t isr = I2CD2.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD2.i2c->ICR = isr & I2C_INT_CLEAR_MASK;
-
- i2c_lld_serve_interrupt(&I2CD2, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) {
- uint32_t isr = I2CD2.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD2.i2c->ICR = isr & I2C_ERROR_MASK;
-
- i2c_lld_serve_error_interrupt(&I2CD2, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-#else
-#error "I2C2 interrupt handlers not defined"
-#endif
-#endif /* STM32_I2C_USE_I2C2 */
-
-#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__)
-#if defined(STM32_I2C3_GLOBAL_HANDLER) || defined(__DOXYGEN__)
-/**
- * @brief I2C3 event interrupt handler.
- *
- * @notapi
- */
-OSAL_IRQ_HANDLER(STM32_I2C3_GLOBAL_HANDLER) {
- uint32_t isr = I2CD3.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD3.i2c->ICR = isr & ~I2C_ISR_ADDR;
-
- if (isr & I2C_ERROR_MASK)
- i2c_lld_serve_error_interrupt(&I2CD3, isr);
- else if (isr & I2C_INT_MASK)
- i2c_lld_serve_interrupt(&I2CD3, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-#elif defined(STM32_I2C3_EVENT_HANDLER) && defined(STM32_I2C3_ERROR_HANDLER)
-OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) {
- uint32_t isr = I2CD3.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD3.i2c->ICR = isr & I2C_INT_CLEAR_MASK;
-
- i2c_lld_serve_interrupt(&I2CD3, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) {
- uint32_t isr = I2CD3.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD3.i2c->ICR = isr & I2C_ERROR_MASK;
-
- i2c_lld_serve_error_interrupt(&I2CD3, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-#else
-#error "I2C3 interrupt handlers not defined"
-#endif
-#endif /* STM32_I2C_USE_I2C3 */
-
-#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__)
-#if defined(STM32_I2C4_GLOBAL_HANDLER) || defined(__DOXYGEN__)
-/**
- * @brief I2C4 event interrupt handler.
- *
- * @notapi
- */
-OSAL_IRQ_HANDLER(STM32_I2C4_GLOBAL_HANDLER) {
- uint32_t isr = I2CD4.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD4.i2c->ICR = isr & ~I2C_ISR_ADDR;
-
- if (isr & I2C_ERROR_MASK)
- i2c_lld_serve_error_interrupt(&I2CD4, isr);
- else if (isr & I2C_INT_MASK)
- i2c_lld_serve_interrupt(&I2CD4, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-#elif defined(STM32_I2C4_EVENT_HANDLER) && defined(STM32_I2C4_ERROR_HANDLER)
-OSAL_IRQ_HANDLER(STM32_I2C4_EVENT_HANDLER) {
- uint32_t isr = I2CD4.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD4.i2c->ICR = isr & I2C_INT_CLEAR_MASK;
-
- i2c_lld_serve_interrupt(&I2CD4, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-OSAL_IRQ_HANDLER(STM32_I2C4_ERROR_HANDLER) {
- uint32_t isr = I2CD4.i2c->ISR;
-
- OSAL_IRQ_PROLOGUE();
-
- /* Clearing IRQ bits.*/
- I2CD4.i2c->ICR = isr & I2C_ERROR_MASK;
-
- i2c_lld_serve_error_interrupt(&I2CD4, isr);
-
- OSAL_IRQ_EPILOGUE();
-}
-
-#else
-#error "I2C4 interrupt handlers not defined"
-#endif
-#endif /* STM32_I2C_USE_I2C4 */
-
-/*===========================================================================*/
-/* Driver exported functions. */
-/*===========================================================================*/
-
-/**
- * @brief Low level I2C driver initialization.
- *
- * @notapi
- */
-void i2c_lld_init(void) {
-
-#if STM32_I2C_USE_I2C1
- i2cObjectInit(&I2CD1);
- I2CD1.thread = NULL;
- I2CD1.i2c = I2C1;
-#if STM32_I2C_USE_DMA == TRUE
- I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM);
- I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM);
-#endif
-#endif /* STM32_I2C_USE_I2C1 */
-
-#if STM32_I2C_USE_I2C2
- i2cObjectInit(&I2CD2);
- I2CD2.thread = NULL;
- I2CD2.i2c = I2C2;
-#if STM32_I2C_USE_DMA == TRUE
- I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM);
- I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM);
-#endif
-#endif /* STM32_I2C_USE_I2C2 */
-
-#if STM32_I2C_USE_I2C3
- i2cObjectInit(&I2CD3);
- I2CD3.thread = NULL;
- I2CD3.i2c = I2C3;
-#if STM32_I2C_USE_DMA == TRUE
- I2CD3.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM);
- I2CD3.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM);
-#endif
-#endif /* STM32_I2C_USE_I2C3 */
-
-#if STM32_I2C_USE_I2C4
- i2cObjectInit(&I2CD4);
- I2CD4.thread = NULL;
- I2CD4.i2c = I2C4;
-#if STM32_I2C_USE_DMA == TRUE
- I2CD4.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C4_RX_DMA_STREAM);
- I2CD4.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C4_TX_DMA_STREAM);
-#endif
-#endif /* STM32_I2C_USE_I2C4 */
-}
-
-/**
- * @brief Configures and activates the I2C peripheral.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-void i2c_lld_start(I2CDriver *i2cp) {
- I2C_TypeDef *dp = i2cp->i2c;
-
-#if STM32_I2C_USE_DMA == TRUE
- /* Common DMA modes.*/
- i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P;
- i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M;
-#endif
-
- /* Make sure I2C peripheral is disabled */
- dp->CR1 &= ~I2C_CR1_PE;
- i2cp->mode = i2cStopped;
-
- /* If in stopped state then enables the I2C and DMA clocks.*/
- if (i2cp->state == I2C_STOP) {
-
-#if STM32_I2C_USE_I2C1
- if (&I2CD1 == i2cp) {
-
- rccResetI2C1();
- rccEnableI2C1(FALSE);
-#if STM32_I2C_USE_DMA == TRUE
- {
- bool b;
-
- b = dmaStreamAllocate(i2cp->dmarx,
- STM32_I2C_I2C1_IRQ_PRIORITY,
- NULL,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
- b = dmaStreamAllocate(i2cp->dmatx,
- STM32_I2C_I2C1_IRQ_PRIORITY,
- NULL,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
-
- i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
- i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
- }
-#endif /* STM32_I2C_USE_DMA == TRUE */
-
-#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__)
- nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY);
-#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER)
- nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY);
- nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY);
-#else
-#error "I2C1 interrupt numbers not defined"
-#endif
- }
-#endif /* STM32_I2C_USE_I2C1 */
-
-#if STM32_I2C_USE_I2C2
- if (&I2CD2 == i2cp) {
-
- rccResetI2C2();
- rccEnableI2C2(FALSE);
-#if STM32_I2C_USE_DMA == TRUE
- {
- bool b;
-
- b = dmaStreamAllocate(i2cp->dmarx,
- STM32_I2C_I2C2_IRQ_PRIORITY,
- NULL,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
- b = dmaStreamAllocate(i2cp->dmatx,
- STM32_I2C_I2C2_IRQ_PRIORITY,
- NULL,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
-
- i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
- i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
- }
-#endif /*STM32_I2C_USE_DMA == TRUE */
-
-#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__)
- nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY);
-#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER)
- nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY);
- nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY);
-#else
-#error "I2C2 interrupt numbers not defined"
-#endif
- }
-#endif /* STM32_I2C_USE_I2C2 */
-
-#if STM32_I2C_USE_I2C3
- if (&I2CD3 == i2cp) {
-
- rccResetI2C3();
- rccEnableI2C3(FALSE);
-#if STM32_I2C_USE_DMA == TRUE
- {
- bool b;
-
- b = dmaStreamAllocate(i2cp->dmarx,
- STM32_I2C_I2C3_IRQ_PRIORITY,
- NULL,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
- b = dmaStreamAllocate(i2cp->dmatx,
- STM32_I2C_I2C3_IRQ_PRIORITY,
- NULL,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
-
- i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
- i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
- }
-#endif /*STM32_I2C_USE_DMA == TRUE */
-
-#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__)
- nvicEnableVector(STM32_I2C3_GLOBAL_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY);
-#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER)
- nvicEnableVector(STM32_I2C3_EVENT_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY);
- nvicEnableVector(STM32_I2C3_ERROR_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY);
-#else
-#error "I2C3 interrupt numbers not defined"
-#endif
- }
-#endif /* STM32_I2C_USE_I2C3 */
-
-#if STM32_I2C_USE_I2C4
- if (&I2CD4 == i2cp) {
-
- rccResetI2C4();
- rccEnableI2C4(FALSE);
-#if STM32_I2C_USE_DMA == TRUE
- {
- bool b;
-
- b = dmaStreamAllocate(i2cp->dmarx,
- STM32_I2C_I2C4_IRQ_PRIORITY,
- NULL,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
- b = dmaStreamAllocate(i2cp->dmatx,
- STM32_I2C_I2C4_IRQ_PRIORITY,
- NULL,
- (void *)i2cp);
- osalDbgAssert(!b, "stream already allocated");
-
- i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C4_RX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY);
- i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C4_TX_DMA_CHANNEL) |
- STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY);
- }
-#endif /*STM32_I2C_USE_DMA == TRUE */
-
-#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__)
- nvicEnableVector(STM32_I2C4_GLOBAL_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY);
-#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER)
- nvicEnableVector(STM32_I2C4_EVENT_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY);
- nvicEnableVector(STM32_I2C4_ERROR_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY);
-#else
-#error "I2C4 interrupt numbers not defined"
-#endif
- }
-#endif /* STM32_I2C_USE_I2C4 */
- }
-
-#if STM32_I2C_USE_DMA == TRUE
- /* I2C registers pointed by the DMA.*/
- dmaStreamSetPeripheral(i2cp->dmarx, &dp->RXDR);
- dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR);
- /* Reset i2c peripheral, the TCIE bit will be handled separately. */
- // TODO: Mask out config bits which user mustn't fiddle with
- dp->CR1 = (i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_NACKIE |
- I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN);
-#else
- /* Reset i2c peripheral, the TCIE bit will be handled separately. No DMA interrupts */
- dp->CR1 = (i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_NACKIE);
-#endif
-
- /* Setup I2C parameters.*/
- dp->TIMINGR = i2cp->config->timingr;
-
- /* Ready to go.*/
- i2cp->mode = i2cIdle;
-#if HAL_USE_I2C_LOCK
- i2cp->lockDuration = TIME_IMMEDIATE;
-#endif
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
- i2cp->slaveNextReply = i2cp->slaveNextRx = &I2CSlaveLockOnMsg;
- i2cp->targetAdr = i2cInvalidAdr;
- i2cp->slaveTimeout = TIME_INFINITE;
-#endif
-
- dp->CR1 |= I2C_CR1_PE; // Enable peripheral
-}
-
-
-/**
- * @brief Deactivates the I2C peripheral.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-void i2c_lld_stop(I2CDriver *i2cp) {
-
- /* If not in stopped state then disables the I2C clock.*/
- if (i2cp->state != I2C_STOP) {
- i2cp->mode = i2cStopped;
-
- /* I2C disable.*/
- stopTimer(i2cp);
- i2c_lld_abort_operation(i2cp);
-#if STM32_I2C_USE_DMA == TRUE
- dmaStreamRelease(i2cp->dmatx);
- dmaStreamRelease(i2cp->dmarx);
-#endif
-
-#if STM32_I2C_USE_I2C1
- if (&I2CD1 == i2cp) {
-#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__)
- nvicDisableVector(STM32_I2C1_GLOBAL_NUMBER);
-#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER)
- nvicDisableVector(STM32_I2C1_EVENT_NUMBER);
- nvicDisableVector(STM32_I2C1_ERROR_NUMBER);
-#else
-#error "I2C1 interrupt numbers not defined"
-#endif
-
- rccDisableI2C1(FALSE);
- }
-#endif
-
-#if STM32_I2C_USE_I2C2
- if (&I2CD2 == i2cp) {
-#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__)
- nvicDisableVector(STM32_I2C2_GLOBAL_NUMBER);
-#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER)
- nvicDisableVector(STM32_I2C2_EVENT_NUMBER);
- nvicDisableVector(STM32_I2C2_ERROR_NUMBER);
-#else
-#error "I2C2 interrupt numbers not defined"
-#endif
-
- rccDisableI2C2(FALSE);
- }
-#endif
-
-#if STM32_I2C_USE_I2C3
- if (&I2CD3 == i2cp) {
-#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__)
- nvicDisableVector(STM32_I2C3_GLOBAL_NUMBER);
-#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER)
- nvicDisableVector(STM32_I2C3_EVENT_NUMBER);
- nvicDisableVector(STM32_I2C3_ERROR_NUMBER);
-#else
-#error "I2C3 interrupt numbers not defined"
-#endif
-
- rccDisableI2C3(FALSE);
- }
-#endif
-
-#if STM32_I2C_USE_I2C4
- if (&I2CD4 == i2cp) {
-#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__)
- nvicDisableVector(STM32_I2C4_GLOBAL_NUMBER);
-#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER)
- nvicDisableVector(STM32_I2C4_EVENT_NUMBER);
- nvicDisableVector(STM32_I2C4_ERROR_NUMBER);
-#else
-#error "I2C4 interrupt numbers not defined"
-#endif
-
- rccDisableI2C4(FALSE);
- }
-#endif
- }
-}
-
-
-
-#if HAL_USE_I2C_MASTER == TRUE
-/**
- * Utility routine brings out common code for master timeout
- */
-static msg_t calcMasterTimeout(I2CDriver *i2cp)
-{
- systime_t start, end;
-
- osalDbgAssert((i2cp->mode <= i2cIsMaster), "busy");
-
- /* Calculating the time window for the timeout on the busy bus condition.*/
- start = osalOsGetSystemTimeX();
- end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT);
-
- /* Waits until BUSY flag is reset or, alternatively, for a timeout
- condition.*/
- while (true) {
- osalSysLock();
-
- /* If the bus is not busy then the operation can continue, note, the
- loop is exited in the locked state.*/
-// if (!(i2cp->i2c->ISR & I2C_ISR_BUSY) && !(i2cp->i2c->CR1 & I2C_CR1_STOP))
- if (!(i2cp->i2c->ISR & I2C_ISR_BUSY))
- break;
-
- /* If the system time went outside the allowed window then a timeout
- condition is returned.*/
- if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end))
- return MSG_TIMEOUT;
-
- osalSysUnlock();
- // TODO: Should we relinquish thread here for a while?
- chThdSleepMilliseconds(2);
- }
- i2cp->mode = i2cIsMaster; // We can set master mode now
- return MSG_OK;
-}
-
-
-/**
- * Start a master mode transaction
- *
- * Note: may need adjustment to work in multi-master mode as well - see i2c_lld_safety_timeout()
- */
-static msg_t startMasterAction(I2CDriver *i2cp, systime_t timeout)
-{
-#if STM32_I2C_USE_DMA == TRUE
-#else
-#endif
- msg_t msg;
-
- /* Starts the operation.*/
- i2cp->i2c->CR2 |= I2C_CR2_START;
-
- /* Waits for the operation completion or a timeout.*/
- msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
-
- /* In case of a software timeout a STOP is sent as an extreme attempt
- to release the bus.*/
- if (msg == MSG_TIMEOUT) {
- i2cp->i2c->CR2 |= I2C_CR2_STOP;
- i2cp->mode = i2cIdle; // TODO: Is this enough?
- }
- return msg;
-}
-
-
-/**
- * @brief Receives data via the I2C bus as master.
- * @details Number of receiving bytes must be more than 1 on STM32F1x. This is
- * hardware restriction.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] addr slave device address
- * @param[out] rxbuf pointer to the receive buffer
- * @param[in] rxbytes number of bytes to be received
- * @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.
- *
- * @notapi
- */
-msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
- uint8_t *rxbuf, size_t rxbytes,
- systime_t timeout) {
-// I2C_TypeDef *dp = i2cp->i2c;
-
- osalDbgAssert((i2cp->thread==NULL), "#3 - reentry");
-
- /* Resetting error flags for this transfer.*/
- i2cp->errors = I2C_NO_ERROR;
-
- /* Releases the lock from high level driver.*/
- osalSysUnlock();
-
- calcMasterTimeout(i2cp); // This has to be done before we change the state of the connection
-
-
-#if STM32_I2C_USE_DMA == TRUE
- /* RX DMA setup.*/
- dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
- dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
- dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
-#endif
- // Always set up the receive buffer in case callbacks enabled
- i2cp->rxptr = rxbuf;
- i2cp->rxbytes = rxbytes;
-
- /* Setting up the slave address.*/
- i2c_lld_set_address(i2cp, addr);
-
- /* Setting up the peripheral.*/
- i2c_lld_setup_rx_transfer(i2cp);
-
- i2cStartReceive(i2cp);
- i2cp->mode = i2cMasterRxing;
-
- return startMasterAction(i2cp, timeout);
-}
-
-
-
-/**
- * @brief Transmits data via the I2C bus as master.
- * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x.
- * This is hardware restriction.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] addr slave device address
- * @param[in] txbuf pointer to the transmit buffer
- * @param[in] txbytes number of bytes to be transmitted
- * @param[out] rxbuf pointer to the receive buffer
- * @param[in] rxbytes number of bytes to be received
- * @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.
- *
- * @notapi
- */
-msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
- const uint8_t *txbuf, size_t txbytes,
- uint8_t *rxbuf, size_t rxbytes,
- systime_t timeout) {
- I2C_TypeDef *dp = i2cp->i2c;
-
- osalDbgAssert((i2cp->thread==NULL), "#3 - reentry");
-
- /* Resetting error flags for this transfer.*/
- i2cp->errors = I2C_NO_ERROR;
-
- /* Releases the lock from high level driver.*/
- osalSysUnlock();
-
- calcMasterTimeout(i2cp); // This has to be done before we change the state of the connection
-
-
-#if STM32_I2C_USE_DMA == TRUE
- /* TX DMA setup.*/
- dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
- dmaStreamSetMemory0(i2cp->dmatx, txbuf);
- dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
-
- /* RX DMA setup, note, rxbytes can be zero but we write the value anyway.*/
- dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
- dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
- dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
-#else
- i2cp->txptr = txbuf;
- i2cp->txbytes = txbytes;
-#endif
- // Always set up the receive buffer in case callbacks enabled
- i2cp->rxptr = rxbuf;
- i2cp->rxbytes = rxbytes;
-
- /* Setting up the slave address.*/
- i2c_lld_set_address(i2cp, addr);
-
- /* Preparing the transfer.*/
- i2c_lld_setup_tx_transfer(i2cp);
-
-#if STM32_I2C_USE_DMA == TRUE
- /* Enabling TX DMA.*/
- dmaStreamEnable(i2cp->dmatx);
-
- /* Transfer complete interrupt enabled.*/
- dp->CR1 |= I2C_CR1_TCIE;
-#else
- /* Transfer complete and TX interrupts enabled.*/
- dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE;
-#endif
-
- i2cp->mode = i2cMasterTxing;
-
- return startMasterAction(i2cp, timeout);
-}
-#endif /* #if HAL_USE_I2C_MASTER == TRUE */
-
-
-
-
-#if HAL_USE_I2C_SLAVE
-/************************************************************************/
-/* SLAVE MODE SUPPORT */
-/************************************************************************/
-
-/**
- * @brief Reconfigure I2C channel to respond to passed address
- * in addition to those previously made active
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cadr I2C network address
- *
- * @return Length of message OR the type of event received
- * @retval I2C_OK Success
- * @retval I2C_ERROR Cannot match address in addition of those already
- *
- * @details MatchAddress calls are cumulative.
- * Specify address zero to match I2C "all call"
- * Does not support 10-bit addressing.
- * Number of supported addresses is chip-dependent - 2+general call on I2CV2
- * Address masking capabilities of OAR2 not supported
- *
- * @notapi
- **/
-msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr)
-{
- I2C_TypeDef *dp = i2cp->i2c;
- if (i2cadr == 0) {
- dp->CR1 |= I2C_CR1_GCEN; // Just enable General Call
- dp->CR1 |= I2C_CR1_ADDRIE; // Make sure address match interrupt enabled
- }
- else
- {
- uint32_t adr = i2cadr << 1;
- if ((dp->OAR1 & (0x7f<<1)) == adr) { return I2C_OK; }; // Already matched in OAR1
- if ((dp->OAR2 & (0x7f<<1)) == adr) { return I2C_OK; }; // Already matched in OAR2
-
- if (!(dp->OAR1 & I2C_OAR1_OA1EN)) {
- dp->OAR1 = adr | I2C_OAR1_OA1EN; // OAR1 previously unused
- dp->CR1 |= I2C_CR1_ADDRIE; // Make sure address match interrupt enabled
- }
- else
- if (!(dp->OAR2 & I2C_OAR2_OA2EN)) {
- dp->OAR2 = adr | I2C_OAR2_OA2EN; // OAR2 previously unused
- dp->CR1 |= I2C_CR1_ADDRIE; // Make sure address match interrupt enabled
- }
- else
- return I2C_ERROR; /* cannot add this address to set of those matched */
- }
- return I2C_OK;
-}
-
-
-/**
- * @brief Reconfigure I2C channel to no longer match specified address
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cadr I2C network address
- *
- * @details A message being transferred that has already matched the
- * specified address will continue being processed.
- * Requests to unmatch an address that is not currently being matched
- * are ignored.
- * Does not support 10-bit addressing.
- *
- * @notapi
- **/
-void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr)
-{
- I2C_TypeDef *dp = i2cp->i2c;
- if (i2cadr == 0) {
- dp->CR1 &= (uint32_t)~I2C_CR1_GCEN; // Disable General Call
- }
- else {
- uint32_t adr = i2cadr << 1;
- if ((dp->OAR1 & (0x7f<<1)) == adr) {
- // Matched in OAR1
- dp->OAR1 &= ~I2C_OAR1_OA1EN; // Just disable - OAR2 is a bit different
- }
- else
- if ((dp->OAR2 & I2C_OAR2_OA2EN) && (dp->OAR2 & (0x7f<<1)) == adr)
- dp->OAR2 &= ~I2C_OAR2_OA2EN;
- }
- if (!((dp->CR1 & (uint32_t)I2C_CR1_GCEN) || (dp->OAR1 & I2C_OAR1_OA1EN) || (dp->OAR2 & I2C_OAR2_OA2EN))) {
- dp->CR1 &= (uint32_t)~(I2C_CR1_ADDRIE); // Disable Address match interrupts if nothing can generate them (strictly necessary??)
- }
-}
-
-
-/**
- * @brief Reconfigure I2C channel to no longer match any address
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @details Causes all subsequent messages to be ignored.
- * A message being transferred that has already matched a
- * slave address will continue being processed.
- *
- * @notapi
- **/
-void i2c_lld_unmatchAll(I2CDriver *i2cp)
-{
- I2C_TypeDef *dp = i2cp->i2c;
- dp->CR1 &= (uint32_t)~(I2C_CR1_GCEN | I2C_CR1_ADDRIE); // Disable General Call
- dp->OAR1 = 0;
- dp->OAR2 = 0;
-}
-
-
-/**
- * @brief Configure callbacks & buffers to receive messages
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent received messages
- *
- * @details Call i2cMatchAddress() after this to start processing
- * Enabling match addresses before installing handler callbacks can
- * result in locking the I2C bus when a master accesses those
- * unconfigured slave addresses
- *
- * @notapi
- */
-void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg)
-{
- osalDbgCheck((rxMsg && rxMsg->size <= 0xffff));
- qEvt(0x82, rxMsg->size);
- i2cp->slaveNextRx = rxMsg;
- if (i2cp->mode == i2cLockedRxing && rxMsg->body && rxMsg->size) {
- /* We can receive now! */
- i2cp->slaveRx = rxMsg;
- /* slave RX DMA setup */
-#if STM32_I2C_USE_DMA == TRUE
- /* RX DMA setup.*/
- dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
- dmaStreamSetMemory0(i2cp->dmarx, rxMsg->body);
- dmaStreamSetTransactionSize(i2cp->dmarx, rxMsg->size);
-#else
- i2cp->rxptr = rxMsg->body;
- i2cp->rxbytes = rxMsg->size;
-#endif
-
- i2cp->mode = i2cSlaveRxing;
- i2c_lld_setup_rx_transfer(i2cp); // Set up the transfer
- qEvt(0x83, 0);
- i2cStartReceive(i2cp);
- i2cp->i2c->CR1 &= ~I2C_CR1_SBC; // Not needed with receive
- i2cp->i2c->ICR = I2C_ISR_ADDR; // We can release the clock stretch now
- }
-}
-
-
-/**
- * @brief Configure callbacks & buffers for query reply
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries
- *
- * @details Call i2cMatchAddress() after this to start processing
- * Enabling match addresses before installing handler callbacks can
- * result in locking the I2C bus when a master accesses those
- * unconfigured slave addresses
- *
- * @notapi
- */
-void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg)
-{
- osalDbgCheck((replyMsg && replyMsg->size <= 0xffff));
- qEvt(0x80, replyMsg->size);
- i2cp->slaveNextReply = replyMsg;
- if (i2cp->mode == i2cLockedReplying && replyMsg->body && replyMsg->size)
- {
- i2cp->slaveReply = replyMsg;
- /* slave TX setup -- we can reply now! */
- #if STM32_I2C_USE_DMA == TRUE
- dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
- dmaStreamSetMemory0(i2cp->dmatx, replyMsg->body);
- dmaStreamSetTransactionSize(i2cp->dmatx, replyMsg->size);
- i2cp->mode = i2cSlaveReplying;
- /* Start transmission */
- i2c_lld_setup_tx_transfer(i2cp);
-
- /* Enabling TX DMA.*/
- dmaStreamEnable(i2cp->dmatx);
-
- /* Transfer complete interrupt enabled.*/
- i2cp->i2c->CR1 |= I2C_CR1_TCIE;
- #else
- /* Start transmission */
- i2cp->txptr = replyMsg->body;
- i2cp->txbytes = replyMsg->size;
- i2c_lld_setup_tx_transfer(i2cp);
- /* Transfer complete and TX character interrupts enabled.*/
- i2cp->i2c->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE;
- #endif
- qEvt(0x81, 0);
- i2cp->i2c->CR1 |= I2C_CR1_SBC; // Need this to enable byte counter in transmit mode
- i2cp->i2c->ICR = I2C_ISR_ADDR; // We can release the clock stretch now
- }
-}
-
-#endif /* HAL_USE_I2C_SLAVE */
-
-
-#endif /* HAL_USE_I2C */
-
-/** @} */
diff --git a/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h b/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h
deleted file mode 100644
index c4df28fb2e..0000000000
--- a/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h
+++ /dev/null
@@ -1,806 +0,0 @@
-/*
- ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-/*
- Concepts and parts of this file have been contributed by Uladzimir Pylinsky
- aka barthess. I2C Slave API for Chibios V2.x V1 I2C originally contributed
- by Brent Roman (brent@mbari.org), ported to Chibios V3, V2 I2C by steved
- */
-
-/**
- * @file STM32/I2Cv2/i2c_lld.h
- * @brief STM32 I2C subsystem low level driver header.
- *
- * @addtogroup I2C
- * @{
- */
-
-#ifndef _I2C_LLD_H_
-#define _I2C_LLD_H_
-
-#if HAL_USE_I2C || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver constants. */
-/*===========================================================================*/
-
-/**
- * @name TIMINGR register definitions
- * @{
- */
-#define STM32_TIMINGR_PRESC_MASK (15U << 28)
-#define STM32_TIMINGR_PRESC(n) ((n) << 28)
-#define STM32_TIMINGR_SCLDEL_MASK (15U << 20)
-#define STM32_TIMINGR_SCLDEL(n) ((n) << 20)
-#define STM32_TIMINGR_SDADEL_MASK (15U << 16)
-#define STM32_TIMINGR_SDADEL(n) ((n) << 16)
-#define STM32_TIMINGR_SCLH_MASK (255U << 8)
-#define STM32_TIMINGR_SCLH(n) ((n) << 8)
-#define STM32_TIMINGR_SCLL_MASK (255U << 0)
-#define STM32_TIMINGR_SCLL(n) ((n) << 0)
-/** @} */
-
-
-/**
- * Driver clears down tidily after a timeout
- */
-#define I2C_SUPPORT_BUS_CLEAR TRUE
-
-/**
- * @brief Invalid I2C bus address
- */
-#define i2cInvalidAdr ((i2caddr_t) -1)
-
-/*===========================================================================*/
-/* Driver pre-compile time settings. */
-/*===========================================================================*/
-
-/**
- * @name Configuration options
- * @{
- */
-/**
- * @brief I2C1 driver enable switch.
- * @details If set to @p TRUE the support for I2C1 is included.
- * @note The default is @p FALSE.
- */
-#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__)
-#define STM32_I2C_USE_I2C1 FALSE
-#endif
-
-/**
- * @brief I2C2 driver enable switch.
- * @details If set to @p TRUE the support for I2C2 is included.
- * @note The default is @p FALSE.
- */
-#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__)
-#define STM32_I2C_USE_I2C2 FALSE
-#endif
-
-/**
- * @brief I2C3 driver enable switch.
- * @details If set to @p TRUE the support for I2C3 is included.
- * @note The default is @p FALSE.
- */
-#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__)
-#define STM32_I2C_USE_I2C3 FALSE
-#endif
-
-/**
- * @brief I2C4 driver enable switch.
- * @details If set to @p TRUE the support for I2C4 is included.
- * @note The default is @p FALSE.
- */
-#if !defined(STM32_I2C_USE_I2C4) || defined(__DOXYGEN__)
-#define STM32_I2C_USE_I2C4 FALSE
-#endif
-
-
-/**
- * @brief Enables support for I2C slave mode operation
- */
-#if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__)
-#define HAL_USE_I2C_SLAVE FALSE
-#endif
-
-
-/**
- * @brief Turns on some debugging options
- */
-#if !defined(STM32_I2C_DEBUG_ENABLE) || defined(__DOXYGEN__)
-#define STM32_I2C_DEBUG_ENABLE FALSE
-#endif
-
-
-/**
- * @brief I2C timeout on busy condition in milliseconds.
- */
-#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__)
-#define STM32_I2C_BUSY_TIMEOUT 50
-#endif
-
-/**
- * @brief I2C1 interrupt priority level setting.
- */
-#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C1_IRQ_PRIORITY 10
-#endif
-
-/**
- * @brief I2C2 interrupt priority level setting.
- */
-#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C2_IRQ_PRIORITY 10
-#endif
-
-/**
- * @brief I2C3 interrupt priority level setting.
- */
-#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C3_IRQ_PRIORITY 10
-#endif
-
-/**
- * @brief I2C4 interrupt priority level setting.
- */
-#if !defined(STM32_I2C_I2C4_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C4_IRQ_PRIORITY 10
-#endif
-
-/**
- * @brief DMA use switch.
- */
-#if !defined(STM32_I2C_USE_DMA) || defined(__DOXYGEN__)
-#define STM32_I2C_USE_DMA TRUE
-#endif
-
-/**
- * @brief I2C1 DMA priority (0..3|lowest..highest).
- * @note The priority level is used for both the TX and RX DMA streams but
- * because of the streams ordering the RX stream has always priority
- * over the TX stream.
- */
-#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C1_DMA_PRIORITY 1
-#endif
-
-/**
- * @brief I2C2 DMA priority (0..3|lowest..highest).
- * @note The priority level is used for both the TX and RX DMA streams but
- * because of the streams ordering the RX stream has always priority
- * over the TX stream.
- */
-#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C2_DMA_PRIORITY 1
-#endif
-
-/**
- * @brief I2C3 DMA priority (0..3|lowest..highest).
- * @note The priority level is used for both the TX and RX DMA streams but
- * because of the streams ordering the RX stream has always priority
- * over the TX stream.
- */
-#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C3_DMA_PRIORITY 1
-#endif
-
-/**
- * @brief I2C4 DMA priority (0..3|lowest..highest).
- * @note The priority level is used for both the TX and RX DMA streams but
- * because of the streams ordering the RX stream has always priority
- * over the TX stream.
- */
-#if !defined(STM32_I2C_I2C4_DMA_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2C_I2C4_DMA_PRIORITY 1
-#endif
-
-/**
- * @brief I2C DMA error hook.
- * @note The default action for DMA errors is a system halt because DMA
- * error can only happen because programming errors.
- */
-#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
-#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
-#endif
-/** @} */
-
-
-/*===========================================================================*/
-/* Derived constants and error checks. */
-/*===========================================================================*/
-
-/** @brief error checks */
-#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1
-#error "I2C1 not present in the selected device"
-#endif
-
-#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2
-#error "I2C2 not present in the selected device"
-#endif
-
-#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3
-#error "I2C3 not present in the selected device"
-#endif
-
-#if STM32_I2C_USE_I2C4 && !STM32_HAS_I2C4
-#error "I2C4 not present in the selected device"
-#endif
-
-#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && !STM32_I2C_USE_I2C3 && \
- !STM32_I2C_USE_I2C4
-#error "I2C driver activated but no I2C peripheral assigned"
-#endif
-
-#if STM32_I2C_USE_I2C1 && \
- !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY)
-#error "Invalid IRQ priority assigned to I2C1"
-#endif
-
-#if STM32_I2C_USE_I2C2 && \
- !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY)
-#error "Invalid IRQ priority assigned to I2C2"
-#endif
-
-#if STM32_I2C_USE_I2C3 && \
- !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY)
-#error "Invalid IRQ priority assigned to I2C3"
-#endif
-
-#if STM32_I2C_USE_I2C4 && \
- !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C4_IRQ_PRIORITY)
-#error "Invalid IRQ priority assigned to I2C4"
-#endif
-
-#if STM32_I2C_USE_DMA == TRUE
-#if STM32_I2C_USE_I2C1 && \
- !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY)
-#error "Invalid DMA priority assigned to I2C1"
-#endif
-
-#if STM32_I2C_USE_I2C2 && \
- !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY)
-#error "Invalid DMA priority assigned to I2C2"
-#endif
-
-#if STM32_I2C_USE_I2C3 && \
- !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY)
-#error "Invalid DMA priority assigned to I2C3"
-#endif
-
-#if STM32_I2C_USE_I2C4 && \
- !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY)
-#error "Invalid DMA priority assigned to I2C4"
-#endif
-
-/* The following checks are only required when there is a DMA able to
- reassign streams to different channels.*/
-#if STM32_ADVANCED_DMA
-/* Check on the presence of the DMA streams settings in mcuconf.h.*/
-#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \
- !defined(STM32_I2C_I2C1_TX_DMA_STREAM))
-#error "I2C1 DMA streams not defined"
-#endif
-
-#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \
- !defined(STM32_I2C_I2C2_TX_DMA_STREAM))
-#error "I2C2 DMA streams not defined"
-#endif
-
-#if STM32_I2C_USE_I2C3 && (!defined(STM32_I2C_I2C3_RX_DMA_STREAM) || \
- !defined(STM32_I2C_I2C3_TX_DMA_STREAM))
-#error "I2C3 DMA streams not defined"
-#endif
-
-#if STM32_I2C_USE_I2C4 && (!defined(STM32_I2C_I2C4_RX_DMA_STREAM) || \
- !defined(STM32_I2C_I2C4_TX_DMA_STREAM))
-#error "I2C4 DMA streams not defined"
-#endif
-
-/* Check on the validity of the assigned DMA channels.*/
-#if STM32_I2C_USE_I2C1 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \
- STM32_I2C1_RX_DMA_MSK)
-#error "invalid DMA stream associated to I2C1 RX"
-#endif
-
-#if STM32_I2C_USE_I2C1 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \
- STM32_I2C1_TX_DMA_MSK)
-#error "invalid DMA stream associated to I2C1 TX"
-#endif
-
-#if STM32_I2C_USE_I2C2 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \
- STM32_I2C2_RX_DMA_MSK)
-#error "invalid DMA stream associated to I2C2 RX"
-#endif
-
-#if STM32_I2C_USE_I2C2 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \
- STM32_I2C2_TX_DMA_MSK)
-#error "invalid DMA stream associated to I2C2 TX"
-#endif
-
-#if STM32_I2C_USE_I2C3 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \
- STM32_I2C3_RX_DMA_MSK)
-#error "invalid DMA stream associated to I2C3 RX"
-#endif
-
-#if STM32_I2C_USE_I2C3 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \
- STM32_I2C3_TX_DMA_MSK)
-#error "invalid DMA stream associated to I2C3 TX"
-#endif
-
-#if STM32_I2C_USE_I2C4 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_RX_DMA_STREAM, \
- STM32_I2C4_RX_DMA_MSK)
-#error "invalid DMA stream associated to I2C4 RX"
-#endif
-
-#if STM32_I2C_USE_I2C4 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_TX_DMA_STREAM, \
- STM32_I2C4_TX_DMA_MSK)
-#error "invalid DMA stream associated to I2C4 TX"
-#endif
-#endif /* STM32_ADVANCED_DMA */
-
-#if !defined(STM32_DMA_REQUIRED)
-#define STM32_DMA_REQUIRED
-#endif
-#endif /* STM32_I2C_USE_DMA == TRUE */
-
-
-
-/*===========================================================================*/
-/* Driver data structures and types. */
-/*===========================================================================*/
-
-/**
- * @brief Type representing an I2C address.
- * @note For a 7-bit address, this takes values 0..0x7f, which are then
- * shifted left one and the R/W bit added when required
- */
-typedef uint16_t i2caddr_t;
-
-/**
- * @brief Type of I2C driver condition flags.
- */
-typedef uint32_t i2cflags_t;
-
-
-/**
- * @brief Type of a structure representing an I2C driver.
- */
-typedef struct I2CDriver I2CDriver;
-
-
-/**
- * @brief Supported modes for the I2C bus.
- * @note Currently not used; retained for future enhancements
- */
-typedef enum {
- OPMODE_I2C = 1,
- OPMODE_SMBUS_DEVICE = 2,
- OPMODE_SMBUS_HOST = 3,
-} i2copmode_t;
-
-
-
-/**
- * @brief Character received I2C notification callback type.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] c received character
- *
- * @param[out] Return 0 if transfer to continue. 1 if transfer to be stopped
- *
- * @note Use only in master mode, to stop a read transaction
- * once a particular character (or sequence of characters) has been received
- */
-typedef uint8_t (*i2cccb_t)(I2CDriver *i2cp, uint16_t c);
-
-
-
-/**
- * @brief Type of I2C driver configuration structure.
- */
-typedef struct {
- /**
- * @brief TIMINGR register initialization.
- * @note Refer to the STM32 reference manual, the values are affected
- * by the system clock settings in mcuconf.h.
- */
- uint32_t timingr;
- /**
- * @brief CR1 register initialization.
- * @note Leave to zero unless you know what you are doing.
- */
- uint32_t cr1;
- /**
- * @brief CR2 register initialization.
- * @note Leave at zero except in special circumstances - most bits controlled via API
- */
- uint32_t cr2;
- /**
- * @brief Character received callback. Return 0 if transfer to continue. 1 if transfer to be stopped
- * @note Use only in master mode. Set to NULL if not used.
- */
- i2cccb_t rxchar_cb;
-} I2CConfig;
-
-
-
-
-
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
-
-typedef struct I2CSlaveMsg I2CSlaveMsg;
-
-/*
- returns the current I2C slave message receive configuration
-*/
-I2CSlaveMsg *i2cSlaveGetReceiveMsg(I2CDriver *i2cp);
-
-
-/*
- returns the current I2C slave message reply configuration
-*/
-I2CSlaveMsg *i2cSlaveGetReplyMsg(I2CDriver *i2cp);
-
-
-/*
- I2C Slave Message Call Back.
- Invoked from interrupt context just after
- the last byte of the message is transferred or slaveAdr is matched.
-
- Use i2cSlaveReceiveMsg() or i2cSlaveReplyMsg() to access
- the relevant message handling configuration
-*/
-typedef void I2CSlaveMsgCB(I2CDriver *i2cp);
-
-
-/*
- I2CSlaveMsg message handling configurations are normally
- stored in read-only memory.
- They describe either a buffer to contain incoming messages from
- a bus master and associated callback functions, or one
- preloaded with an outgoing reply to a read request and its callbacks.
-*/
-
-struct I2CSlaveMsg {
- size_t size; /* sizeof(body) -- zero if master must wait */
- uint8_t *body; /* message contents -- or NULL if master must wait */
- I2CSlaveMsgCB *adrMatched; /* invoked when slave address matches */
- I2CSlaveMsgCB *processMsg; /* invoked after message is transferred */
- I2CSlaveMsgCB *exception; /* invoked if error or timeout during transfer */
-};
-
-
-/*
- dummy callback -- placeholder to ignore event
-*/
-I2CSlaveMsgCB I2CSlaveDummyCB;
-
- /* lock bus on receive or reply -- force master to wait */
-extern const I2CSlaveMsg I2CSlaveLockOnMsg;
-
-#endif /* HAL_USE_I2C_SLAVE */
-
-
-
-
-/**
- * @brief Structure representing an I2C driver.
- */
-struct I2CDriver {
- /**
- * @brief Driver state.
- */
- i2cstate_t state;
- /**
- * @brief Current configuration data.
- */
- const I2CConfig *config;
- /**
- * @brief Error flags.
- */
- i2cflags_t errors;
-#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
- mutex_t mutex;
-#endif /* I2C_USE_MUTUAL_EXCLUSION */
-#if defined(I2C_DRIVER_EXT_FIELDS)
- I2C_DRIVER_EXT_FIELDS
-#endif
- /* End of the mandatory fields.*/
- /**
- * @brief Thread waiting for I/O completion.
- */
- thread_reference_t thread;
-
-
-#if (STM32_I2C_USE_DMA == TRUE) || defined(__DOXYGEN__)
- /**
- * @brief RX DMA mode bit mask.
- */
- uint32_t rxdmamode;
- /**
- * @brief TX DMA mode bit mask.
- */
- uint32_t txdmamode;
- /**
- * @brief Receive DMA channel.
- */
- const stm32_dma_stream_t *dmarx;
- /**
- * @brief Transmit DMA channel.
- */
- const stm32_dma_stream_t *dmatx;
-#else /* STM32_I2C_USE_DMA == FALSE */
- /**
- * @brief Pointer to the next TX buffer location.
- */
- const uint8_t *txptr;
- /**
- * @brief Number of bytes in TX phase.
- */
- size_t txbytes;
-#endif /* STM32_I2C_USE_DMA == FALSE */
- /**
- * @brief Pointer to the next RX buffer location.
- */
- uint8_t *rxptr;
- /**
- * @brief Number of bytes in RX phase.
- */
- size_t rxbytes;
- /**
- * @brief Pointer to the I2Cx registers block.
- */
- I2C_TypeDef *i2c;
-
-
- /**
- * @brief low level I2C interface / protocol state
- */
- enum i2cMode {
- i2cStopped = 0, /* Port not initialised, or not started */
- i2cIdle=1, /* awaiting address or inactive */
- i2cSlaveRxing, /* receiving message */
- i2cLockedRxing, /* stretching clock before receiving message - Rx buffer might be full */
- i2cSlaveReplying, /* replying to query (transmitting, slave mode) */
- i2cLockedReplying, /* stretching clock before replying to query (no response available from main code) */
-
- i2cIsMaster=0x11, /* sent start bit (mastering bus) */
- i2cMasterStarted, /* repeated start after write */
- i2cMasterSelecting, /* sending slave address */
- i2cMasterRxing, /* receiving reply from slave */
- i2cMasterTxing /* sending message to slave */
- } mode;
-
-#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE
- /**
- * @brief I2C transaction timer
- * @note USed for slave mode, lock
- */
- virtual_timer_t timer;
-#endif
-#if HAL_USE_I2C_LOCK
- /**
- * @brief I2C bus lock duration
- */
- systime_t lockDuration;
-#endif
-#if HAL_USE_I2C_SLAVE
- /* additional fields to support I2C slave transactions */
-
- /**
- * @brief slave address of message being processed
- */
- i2caddr_t targetAdr;
- /**
- * @brief Error Mask for last slave message
- */
- i2cflags_t slaveErrors;
- /**
- * @brief Length of most recently transferred slave message
- */
- size_t slaveBytes;
- /**
- * @brief Maximum # of ticks slave may stretch the I2C clock
- */
- systime_t slaveTimeout;
- /**
- * @brief Pointer to slave message reception handler
- */
- const I2CSlaveMsg *slaveRx;
- /**
- * @brief Pointer to slave message Reply (transmit) handler
- *
- * @note This is the currently active/just completed reply
- */
- const I2CSlaveMsg *slaveReply;
- /**
- * @brief Pointer to handler for next slave received message
- */
- const I2CSlaveMsg *slaveNextRx;
- /**
- * @brief Pointer to handler for next slave reply (transmit) message
- *
- * @note This is used for a reply if no message received first
- */
- const I2CSlaveMsg *slaveNextReply;
-#endif
-};
-
-/*===========================================================================*/
-/* Driver macros. */
-/*===========================================================================*/
-
-/**
- * @brief Get errors from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
-
-
-
-#if HAL_USE_I2C_LOCK
-/**
- * @brief Unlock I2C bus after the end of the next transaction
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- **/
-#define i2c_lld_unlock(i2cp) (i2cp->lockDuration = TIME_IMMEDIATE)
-#endif
-
-
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
-/**
- * @brief Get slave errors from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveErrors(i2cp) ((i2cp)->slaveErrors)
-
-/**
- * @brief Get slave message bytes transferred from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveBytes(i2cp) ((i2cp)->slaveBytes)
-
-
-/**
- * @brief Get slave timeout in ticks from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveTimeout(i2cp) ((i2cp)->slaveTimeout)
-
-/**
- * @brief Set slave timeout in ticks for I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_set_slaveTimeout(i2cp,ticks) ((i2cp)->slaveTimeout=(ticks))
-
-/**
- * @brief Get slave target address from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveTargetAdr(i2cp) ((i2cp)->targetAdr)
-
-/**
- * @brief Get slave receive message descriptor from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveReceive(i2cp) ((i2cp)->slaveNextRx)
-
-/**
- * @brief Get slave reply message descriptor from I2C driver.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define i2c_lld_get_slaveReply(i2cp) ((i2cp)->slaveNextReply)
-
-
-#endif
-
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-#if !defined(__DOXYGEN__)
-#if STM32_I2C_USE_I2C1
-extern I2CDriver I2CD1;
-#endif
-
-#if STM32_I2C_USE_I2C2
-extern I2CDriver I2CD2;
-#endif
-
-#if STM32_I2C_USE_I2C3
-extern I2CDriver I2CD3;
-#endif
-
-#if STM32_I2C_USE_I2C4
-extern I2CDriver I2CD4;
-#endif
-
-#endif /* !defined(__DOXYGEN__) */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
- void i2c_lld_init(void);
- void i2c_lld_start(I2CDriver *i2cp);
- void i2c_lld_stop(I2CDriver *i2cp);
- msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
- const uint8_t *txbuf, size_t txbytes,
- uint8_t *rxbuf, size_t rxbytes,
- systime_t timeout);
- msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
- uint8_t *rxbuf, size_t rxbytes,
- systime_t timeout);
-
-#if HAL_USE_I2C_LOCK /* I2C slave mode support */
- void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration);
-#endif
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
- msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr);
- void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr);
- void i2c_lld_unmatchAll(I2CDriver *i2cp);
- void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg);
- void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg);
-
-#if STM32_I2C_DEBUG_ENABLE
- void i2cPrintQ(BaseSequentialStream *chp); // Debugging routine
-#endif /* STM32_I2C_DEBUG_ENABLE */
-
-#endif /* HAL_USE_I2C_SLAVE */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HAL_USE_I2C */
-
-#endif /* _I2C_LLD_H_ */
-
-/** @} */
diff --git a/drivers/chibios/i2cslave/hal_i2c.c b/drivers/chibios/i2cslave/hal_i2c.c
deleted file mode 100644
index 5e4e6438c2..0000000000
--- a/drivers/chibios/i2cslave/hal_i2c.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-/*
- Concepts and parts of this file have been contributed by Uladzimir Pylinsky
- aka barthess.
- */
-
-/**
- * @file i2c.c
- * @brief I2C Driver code.
- *
- * @addtogroup I2C
- * @{
- */
-#include "hal.h"
-
-#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver local definitions. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported variables. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local variables and types. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local functions. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported functions. */
-/*===========================================================================*/
-
-/**
- * @brief I2C Driver initialization.
- * @note This function is implicitly invoked by @p halInit(), there is
- * no need to explicitly initialize the driver.
- *
- * @init
- */
-void i2cInit(void) {
-
- i2c_lld_init();
-}
-
-/**
- * @brief Initializes the standard part of a @p I2CDriver structure.
- *
- * @param[out] i2cp pointer to the @p I2CDriver object
- *
- * @init
- */
-void i2cObjectInit(I2CDriver *i2cp) {
-
- i2cp->state = I2C_STOP;
- i2cp->config = NULL;
-
-#if I2C_USE_MUTUAL_EXCLUSION == TRUE
-#if CH_CFG_USE_MUTEXES
- osalMutexObjectInit(&i2cp->mutex);
-#else
- osalSemObjectInit(&i2cp->semaphore, 1);
-#endif /* CH_CFG_USE_MUTEXES */
-#endif /* I2C_USE_MUTUAL_EXCLUSION */
-
-#if defined(I2C_DRIVER_EXT_INIT_HOOK)
- I2C_DRIVER_EXT_INIT_HOOK(i2cp);
-#endif
-}
-
-/**
- * @brief Configures and activates the I2C peripheral.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] config pointer to the @p I2CConfig object
- *
- * @api
- */
-void i2cStart(I2CDriver *i2cp, const I2CConfig *config) {
-
- osalDbgCheck((i2cp != NULL) && (config != NULL));
- osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) ||
- (i2cp->state == I2C_LOCKED), "invalid state");
-
- osalSysLock();
- i2cp->config = config;
- i2c_lld_start(i2cp);
- i2cp->state = I2C_READY;
- osalSysUnlock();
-}
-
-/**
- * @brief Deactivates the I2C peripheral.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @api
- */
-void i2cStop(I2CDriver *i2cp) {
-
- osalDbgCheck(i2cp != NULL);
- osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) ||
- (i2cp->state == I2C_LOCKED), "invalid state");
-
- osalSysLock();
- i2c_lld_stop(i2cp);
- i2cp->state = I2C_STOP;
- osalSysUnlock();
-}
-
-/**
- * @brief Returns the errors mask associated to the previous operation.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @return The errors mask.
- *
- * @api
- */
-i2cflags_t i2cGetErrors(I2CDriver *i2cp) {
-
- osalDbgCheck(i2cp != NULL);
-
- return i2c_lld_get_errors(i2cp);
-}
-
-/**
- * @brief Sends data via the I2C bus.
- * @details Function designed to realize "read-through-write" transfer
- * paradigm. If you want transmit data without any further read,
- * than set @b rxbytes field to 0.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] addr slave device address (7 bits) without R/W bit
- * @param[in] txbuf pointer to transmit buffer
- * @param[in] txbytes number of bytes to be transmitted
- * @param[out] rxbuf pointer to receive buffer
- * @param[in] rxbytes number of bytes to be received, set it to 0 if
- * you want transmit only
- * @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.
- *
- * @api
- */
-msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp,
- i2caddr_t addr,
- const uint8_t *txbuf,
- size_t txbytes,
- uint8_t *rxbuf,
- size_t rxbytes,
- systime_t timeout) {
- msg_t rdymsg;
-
- osalDbgCheck((i2cp != NULL) && (addr != 0U) &&
- (txbytes > 0U) && (txbuf != NULL) &&
- ((rxbytes == 0U) || ((rxbytes > 0U) && (rxbuf != 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_master_transmit_timeout(i2cp, addr, txbuf, txbytes,
- rxbuf, rxbytes, timeout);
- if (rdymsg == MSG_TIMEOUT) {
- i2cp->state = I2C_LOCKED;
- }
- else {
- i2cp->state = I2C_READY;
- }
- osalSysUnlock();
- return rdymsg;
-}
-
-/**
- * @brief Receives data from the I2C bus.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] addr slave device address (7 bits) without R/W bit
- * @param[out] rxbuf pointer to receive buffer
- * @param[in] rxbytes number of bytes to be received
- * @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.
- *
- * @api
- */
-msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp,
- i2caddr_t addr,
- uint8_t *rxbuf,
- size_t rxbytes,
- systime_t timeout){
-
- msg_t rdymsg;
-
- osalDbgCheck((i2cp != NULL) && (addr != 0U) &&
- (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_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, timeout);
- if (rdymsg == MSG_TIMEOUT) {
- i2cp->state = I2C_LOCKED;
- }
- else {
- i2cp->state = I2C_READY;
- }
- osalSysUnlock();
- return rdymsg;
-}
-
-
-#if HAL_USE_I2C_LOCK /* I2C slave mode support */
-
-/**
- * @brief Lock I2C bus at the beginning of the next message sent
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] lockDuration max number of ticks to hold bus locked
- * - @a TIME_INFINITE no timeout.
- * - @a TIME_IMMEDIATE unlock the bus immediately
- * .
- *
- * @api
- */
-void i2cLock(I2CDriver *i2cp, systime_t lockDuration)
-{
- chDbgCheck((i2cp != NULL), "i2cLock");
- chSysLock();
- i2c_lld_lock(i2cp, lockDuration);
- chSysUnlock();
-}
-
-/**
- * @brief Unlock I2C bus after the end of the next transaction
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @api
- **/
-void i2cUnlock(I2CDriver *i2cp)
-{
- chDbgCheck((i2cp != NULL), "i2cUnlock");
- chSysLock();
- i2c_lld_unlock(i2cp);
- chSysUnlock();
-}
-#endif
-
-
-#if HAL_USE_I2C_SLAVE /* I2C slave mode support */
-
-/**
- * @brief Reconfigure I2C channel to respond to indicated address
- * in addition to those already matched
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cadr I2C network address
- *
- * @return Length of message OR the type of event received
- * @retval I2C_OK Success
- * @retval I2C_ERROR Cannot match address in addition of those already
- *
- * @details MatchAddress calls are cumulative.
- * Specify address zero to match I2C "all call"
- * Does not support 10-bit addressing.
- *
- * @api
- **/
-msg_t i2cMatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr)
-{
- osalDbgCheck((i2cp != NULL));
- chSysLock();
- msg_t result = i2c_lld_matchAddress(i2cp, i2cadr);
- chSysUnlock();
- return result;
-}
-
-
-/**
- * @brief Configure to ignore messages directed to the given i2cadr
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cadr I2C bus address
- * - @a 0 matches "all call"
- * .
- * @details A message being transferred that has already matched the
- * specified address will continue being processed.
- * Requests to unmatch an address that is not currently being matched
- * are ignored.
- *
- * @api
- */
-void i2cUnmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr)
-{
- osalDbgCheck((i2cp != NULL));
- chSysLock();
- i2c_lld_unmatchAddress(i2cp, i2cadr);
- chSysUnlock();
-}
-
-
-/**
- * @brief Reconfigure I2C channel to no longer match any address
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @details Causes all subsequent messages to be ignored.
- * A message being transferred that has already matched a
- * slave address will continue being processed.
- *
- * @api
- **/
-void i2cUnmatchAll(I2CDriver *i2cp)
-{
- osalDbgCheck((i2cp != NULL));
- chSysLock();
- i2c_lld_unmatchAll(i2cp);
- chSysUnlock();
-}
-
-
-/**
- * @brief Configure callbacks & buffers for message reception & query reply
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages
- * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries
- *
- * @details Must be called from a thread
- * Call i2cMatchAddress() after this to start processing
- * Enabling match addresses before installing handler callbacks can
- * result in locking the I2C bus when a master accesses those
- * unconfigured slave addresses
- *
- * @api
- */
-void i2cSlaveConfigure(I2CDriver *i2cp,
- const I2CSlaveMsg *rxMsg, const I2CSlaveMsg *replyMsg)
-{
- osalDbgCheck((i2cp != NULL));
- chSysLock();
- i2c_lld_slaveReceive(i2cp, rxMsg);
- i2c_lld_slaveReply(i2cp, replyMsg);
- chSysUnlock();
-}
-
-
-/**
- * @brief Configure callbacks & buffers for query reply
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries
- *
- * @details Call i2cMatchAddress() after this to start processing
- * Enabling match addresses before installing handler callbacks can
- * result in locking the I2C bus when a master accesses those
- * unconfigured slave addresses
- *
- * @api
- */
-void i2cSlaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg)
-{
- osalDbgCheck((i2cp != NULL && rxMsg != NULL));
- chSysLock();
- i2c_lld_slaveReceive(i2cp, rxMsg);
- chSysUnlock();
-}
-
-
-/**
- * @brief Configure callbacks & buffers for query reply
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries
- *
- * @details Call i2cMatchAddress() after this to start processing
- * Enabling match addresses before installing handler callbacks can
- * result in locking the I2C bus when a master accesses those
- * unconfigured slave addresses
- *
- * @api
- */
-void i2cSlaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg)
-{
- osalDbgCheck((i2cp != NULL && replyMsg != NULL));
- chSysLock();
- i2c_lld_slaveReply(i2cp, replyMsg);
- chSysUnlock();
-}
-
-#endif /* HAL_USE_I2C_SLAVE */
-
-
-#if I2C_USE_MUTUAL_EXCLUSION == TRUE || defined(__DOXYGEN__)
-/**
- * @brief Gains exclusive access to the I2C bus.
- * @details This function tries to gain ownership to the I2C bus, if the bus
- * is already being used then the invoking thread is queued.
- * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION
- * must be enabled.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @api
- */
-void i2cAcquireBus(I2CDriver *i2cp) {
-
- osalDbgCheck(i2cp != NULL);
-
-#if CH_CFG_USE_MUTEXES
- osalMutexLock(&i2cp->mutex);
-#elif CH_CFG_USE_SEMAPHORES
- osalSemWait(&i2cp->semaphore);
-#endif /* CH_CFG_USE_MUTEXES */
-}
-
-
-/**
- * @brief Releases exclusive access to the I2C bus.
- * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION
- * must be enabled.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @api
- */
-void i2cReleaseBus(I2CDriver *i2cp) {
-
- osalDbgCheck(i2cp != NULL);
-
-#if CH_CFG_USE_MUTEXES
- osalMutexUnlock(&i2cp->mutex);
-#elif CH_CFG_USE_SEMAPHORES
- osalSemSignal(&i2cp->semaphore);
-#endif /* CH_CFG_USE_MUTEXES */
-}
-
-#endif /* I2C_USE_MUTUAL_EXCLUSION == TRUE */
-
-#endif /* HAL_USE_I2C == TRUE */
-
-/** @} */
diff --git a/drivers/chibios/i2cslave/hal_i2c.h b/drivers/chibios/i2cslave/hal_i2c.h
deleted file mode 100644
index 325941b953..0000000000
--- a/drivers/chibios/i2cslave/hal_i2c.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-/*
- Concepts and parts of this file have been contributed by Uladzimir Pylinsky
- aka barthess.
- */
-
-/**
- * @file i2c.h
- * @brief I2C Driver macros and structures.
- *
- * @addtogroup I2C
- * @{
- */
-
-#ifndef _I2C_H_
-#define _I2C_H_
-
-#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver constants. */
-/*===========================================================================*/
-
-/**
- * @name I2C bus error conditions
- * @{
- */
-#define I2C_NO_ERROR 0x00 /**< @brief No error. */
-#define I2C_BUS_ERROR 0x01 /**< @brief Bus Error. */
-#define I2C_ARBITRATION_LOST 0x02 /**< @brief Arbitration Lost. */
-#define I2C_ACK_FAILURE 0x04 /**< @brief Acknowledge Failure. */
-#define I2C_OVERRUN 0x08 /**< @brief Overrun/Underrun. */
-#define I2C_PEC_ERROR 0x10 /**< @brief PEC Error in
- reception. */
-#define I2C_TIMEOUT 0x20 /**< @brief Hardware timeout. */
-#define I2C_SMB_ALERT 0x40 /**< @brief SMBus Alert. */
-#define I2C_UNKNOWN_ERROR 0x80 /**< @brief internal error (base value - current mode value added) */
-
-#define I2C_STOPPED ((i2cflags_t)(-1))
- /**< @brief stop condition or i2cStop() called */
-/** @} */
-
-/**
- * @name I2C function return codes
- * @{
- */
-#define I2C_OK (MSG_OK)
-#define I2C_ERR_TIMEOUT (MSG_TIMEOUT)
-#define I2C_ERROR (MSG_RESET)
-/** @} */
-
-
-/*===========================================================================*/
-/* Driver pre-compile time settings. */
-/*===========================================================================*/
-
-/**
- * @brief Enables the mutual exclusion APIs on the I2C bus.
- */
-#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
-#define I2C_USE_MUTUAL_EXCLUSION TRUE
-#endif
-
-/**
- * @brief Enables 'lock' capability needed in I2C slave mode
- */
-#if !defined(HAL_USE_I2C_LOCK) || defined(__DOXYGEN__)
-#define HAL_USE_I2C_LOCK FALSE
-#endif
-
-/**
- * @brief Determines whether master mode required to be supported
- */
- #if !defined(HAL_USE_I2C_MASTER) || defined(__DOXYGEN__)
- #define HAL_USE_I2C_MASTER TRUE
- #endif
-
-/**
- * @brief Determines whether slave mode required to be supported
- */
- #if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__)
- #define HAL_USE_I2C_SLAVE FALSE
- #endif
-
-/*===========================================================================*/
-/* Derived constants and error checks. */
-/*===========================================================================*/
-
-#if I2C_USE_MUTUAL_EXCLUSION && !CH_CFG_USE_MUTEXES && !CH_CFG_USE_SEMAPHORES
-#error "I2C_USE_MUTUAL_EXCLUSION requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES"
-#endif
-
-/*===========================================================================*/
-/* Driver data structures and types. */
-/*===========================================================================*/
-
-/**
- * @brief Driver state machine possible states.
- */
-typedef enum {
- I2C_UNINIT = 0, /**< Not initialized. */
- I2C_STOP = 1, /**< Stopped. */
- I2C_READY = 2, /**< Ready. */
- I2C_ACTIVE_TX = 3, /**< Transmitting. */
- I2C_ACTIVE_RX = 4, /**< Receiving. */
- I2C_LOCKED = 5 /**> Bus or driver locked. */
-} i2cstate_t;
-
-#include "hal_i2c_lld.h"
-
-/*===========================================================================*/
-/* Driver macros. */
-/*===========================================================================*/
-
-/**
- * @brief Wakes up the waiting thread notifying no errors.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define _i2c_wakeup_isr(i2cp) do { \
- osalSysLockFromISR(); \
- osalThreadResumeI(&(i2cp)->thread, MSG_OK); \
- osalSysUnlockFromISR(); \
-} while(0)
-
-/**
- * @brief Wakes up the waiting thread notifying errors.
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @notapi
- */
-#define _i2c_wakeup_error_isr(i2cp) do { \
- osalSysLockFromISR(); \
- osalThreadResumeI(&(i2cp)->thread, MSG_RESET); \
- osalSysUnlockFromISR(); \
-} while(0)
-
-/**
- * @brief Wrap i2cMasterTransmitTimeout function with TIME_INFINITE timeout.
- * @api
- */
-#define i2cMasterTransmit(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes) \
- (i2cMasterTransmitTimeout(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes, \
- TIME_INFINITE))
-
-/**
- * @brief Wrap i2cMasterReceiveTimeout function with TIME_INFINITE timeout.
- * @api
- */
-#define i2cMasterReceive(i2cp, addr, rxbuf, rxbytes) \
- (i2cMasterReceiveTimeout(i2cp, addr, rxbuf, rxbytes, TIME_INFINITE))
-
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
- void i2cInit(void);
- void i2cObjectInit(I2CDriver *i2cp);
- void i2cStart(I2CDriver *i2cp, const I2CConfig *config);
- void i2cStop(I2CDriver *i2cp);
- i2cflags_t i2cGetErrors(I2CDriver *i2cp);
- msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp,
- i2caddr_t addr,
- const uint8_t *txbuf, size_t txbytes,
- uint8_t *rxbuf, size_t rxbytes,
- systime_t timeout);
- msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp,
- i2caddr_t addr,
- uint8_t *rxbuf, size_t rxbytes,
- systime_t timeout);
-
-#if HAL_USE_I2C_LOCK /* I2C slave mode support */
- void i2cLock(I2CDriver *i2cp, systime_t lockDuration);
- void i2cUnlock(I2CDriver *i2cp);
-#endif
-
-#if I2C_USE_MUTUAL_EXCLUSION == TRUE
- void i2cAcquireBus(I2CDriver *i2cp);
- void i2cReleaseBus(I2CDriver *i2cp);
-#endif /* I2C_USE_MUTUAL_EXCLUSION */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HAL_USE_I2C == TRUE */
-
-#endif /* _I2C_H_ */
-
-/** @} */
diff --git a/drivers/chibios/i2cslave/hal_i2cslave.h b/drivers/chibios/i2cslave/hal_i2cslave.h
deleted file mode 100644
index 955b41e25c..0000000000
--- a/drivers/chibios/i2cslave/hal_i2cslave.h
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
- 2011,2012,2013 Giovanni Di Sirio.
-
- This file is part of ChibiOS/RT.
-
- ChibiOS/RT is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- ChibiOS/RT is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
- ---
-
- A special exception to the GPL can be applied should you wish to distribute
- a combined work that includes ChibiOS/RT, without being obliged to provide
- the source code for any proprietary components. See the file exception.txt
- for full details of how and when the exception can be applied.
-*/
-/*
- Slave I2C support contributed by Brent Roman of the
- Monterey Bay Aquarium Research Institute
- */
-
-/**
- * @file i2cslave.h
- * @brief Slave Mode for the I2C Driver.
- *
- * @addtogroup I2C
- * @{
- */
-#ifndef _I2CSLAVE_H_
-#define _I2CSLAVE_H_
-
-#if HAL_USE_I2C_SLAVE || defined(__DOXYGEN__)
-
-#include
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Configure to respond to messages directed to the given i2cadr
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cadr I2C bus address
- * - @a 0 matches "all call"
- * .
- * @return Length of message OR the type of event received
- * @retval I2C_OK Success
- * @retval I2C_ERROR Cannot match address in addition of those already
- *
- * @details MatchAddress calls are cumulative.
- * Specify address zero to match I2C "all call"
- * Most hardware supports matching only a signle nonzero address.
- *
- * @api
- */
-int i2cMatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr);
-
-
-/**
- * @brief Configure to ignore messages directed to the given i2cadr
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cadr I2C bus address
- * - @a 0 matches "all call"
- * .
- * @details A message being transferred that has already matched the
- * specified address will continue being processed.
- * Requests to unmatch an address that is not currently being matched
- * are ignored.
- *
- * @api
- */
-void i2cUnmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr);
-
-
-/**
- * @brief Configure to ignore all messages
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @details A message being transferred that has already matched the
- * specified address will continue being processed.
- *
- * @api
- */
-void i2cUnmatchAll(I2CDriver *i2cp);
-
-
-/**
- * @brief Configure to respond to messages directed to the given i2cadr
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cadr I2C bus address
- * - @a 0 matches "all call"
- * .
- * @return non-zero implies failure.
- *
- * @details Identical to i2cMatchAddress(), but called from interrupt context
- *
- * @api
- */
-static inline msg_t
- i2cMatchAddressI(I2CDriver *i2cp, i2caddr_t i2cadr)
-{
- osalDbgCheck(i2cp != NULL);
- return i2c_lld_matchAddress(i2cp, i2cadr);
-}
-
-
-/**
- * @brief Configure to ignore messages directed to the given i2cadr
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] i2cadr I2C bus address
- * - @a 0 matches "all call"
- * .
- * @details Identical to i2cUnmatchAddress(), but called from interrupt context
- *
- * @api
- */
-static inline void
- i2cUnmatchAddressI(I2CDriver *i2cp, i2caddr_t i2cadr)
-{
- osalDbgCheck(i2cp != NULL);
- i2c_lld_unmatchAddress(i2cp, i2cadr);
-}
-
-
-/**
- * @brief Configure to ignore all messages
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @details Identical to i2cUnmatchAll(), but called from interrupt context
- *
- * @api
- */
-static inline void
- i2cUnmatchAllI(I2CDriver *i2cp)
-/*
- Notes:
- Must be called from interrupt context
- Does not affect the processing of any message currently being received
-*/
-{
- osalDbgCheck(i2cp != NULL);
- i2c_lld_unmatchAll(i2cp);
-}
-
-
-/* I2C Bus activity timeout configuration */
-
-/**
- * @brief return maximum number of ticks a slave bus transaction may last
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @return maximum number of ticks a slave bus transaction my last
- *
- * @details initialized to TIME_INFINITE (disabling slave mode bus timeouts)
- *
- * @api
- */
-static inline
- systime_t i2cSlaveTimeout(I2CDriver *i2cp)
-{
- osalDbgCheck(i2cp != NULL);
- return i2c_lld_get_slaveTimeout(i2cp);
-}
-
-
-/**
- * @brief set the maximum number of ticks a slave bus transaction may last
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] ticks maximum number of ticks a slave bus transaction my last
- * - @a TIME_INFINITE disables slave mode bus timeouts
- * - @a TIME_IMMEDIATE is invalid
- * .
- *
- * @api
- */
-static inline
- void i2cSlaveSetTimeout(I2CDriver *i2cp, systime_t ticks)
-{
- osalDbgCheck(i2cp != NULL && ticks != TIME_IMMEDIATE);
- i2c_lld_set_slaveTimeout(i2cp, ticks);
-}
-
-
-/* bus transaction attributes */
-
-/**
- * @brief return bit mask of errors associated with this slave transaction
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @return I2C bus error conditions described in i2c.h
- *
- * @api
- */
-static inline
- i2cflags_t i2cSlaveErrors(I2CDriver *i2cp)
-{
- osalDbgCheck(i2cp != NULL);
- return i2c_lld_get_slaveErrors(i2cp);
-}
-
-/**
- * @brief return number of bytes transferred during this slave transaction
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @return number of bytes actually transferred on the bus
- *
- * @api
- */
-static inline
- size_t i2cSlaveBytes(I2CDriver *i2cp)
-{
- osalDbgCheck(i2cp != NULL);
- return i2c_lld_get_slaveBytes(i2cp);
-}
-
-/**
- * @brief return i2c address to which this message was targetted
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- *
- * @return i2c address to which this message was targetted
- *
- * @details The address returns will be one of those
- * specified earlier as an argument to i2cMatchAddress()
- *
- * @api
- */
-static inline
- i2caddr_t i2cSlaveTargetAdr(I2CDriver *i2cp)
-{
- osalDbgCheck(i2cp != NULL);
- return i2c_lld_get_slaveTargetAdr(i2cp);
-}
-
-
-/*
- An event service thread based API library called i2cevent supports processing
- slave messages on a dedicated thread. This facility is built upon the
- low-level driver's asynchronous callback functions described below:
-
- Each callback function may alter the processing of subsequent I2C
- messages and read requests by calling i2cSlaveReceive() and
- i2cSlaveReply(), respectively. Further, callbacks may alter their
- i2cSlaveMsg structs in RAM, but only those for their own channel.
- Such changes take immediate affect. This facility can be used to
- avoid copying message buffers.
-
- If receive buffers become full or a reply to a read request cannot be
- generated immediately, the relevant I2CSlaveMsg struct may be substituted
- for another whose body pointer is NULL or whose body size is zero.
- Note that, I2CSlaveMsg structs may be modified
- in place within a channel's callbacks to the same effect.
-
- A NULL body pointer or zero size causes the slave to signal the master node
- to wait by holding the I2C clock signal low, "stretching it", during the next
- transaction to which that I2CSlaveMsg applies.
- The I2C clock resumes only after a i2cSlaveSetReceive() or SetReply() is
- called with an I2CSlaveMsg containing a non-NULL body,
- or after the transaction timeout expires.
-
- Therefore, if a NULL body pointer is replaced with a non-NULL one or
- a zero length is replaced with a non-zero one, i2cSlaveReceive() or
- i2cSlaveReply() MUST be called -- even if with the same pointer values --
- to inform the i2c driver that the transaction may resume.
-
- Note that Receive and Reply processing is initially "locked".
-*/
-
-/**
- * @brief Configure callbacks & buffers for message reception & query reply
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages
- * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries
- *
- * @details Must be called from a thread
- * Call i2cMatchAddress() after this to start processing
- * Enabling match addresses before installing handler callbacks can
- * result in locking the I2C bus when a master accesses those
- * unconfigured slave addresses
- *
- * @api
- */
-void i2cSlaveConfigure(I2CDriver *i2cp,
- const I2CSlaveMsg *rxMsg, const I2CSlaveMsg *replyMsg);
-
-
-/**
- * @brief Configure callbacks & buffers for message reception
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages
- * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries
- *
- * @details Must be called from a thread
- * Call i2cMatchAddress() after this to start processing
- * Enabling match addresses before installing handler callbacks can
- * result in locking the I2C bus when a master accesses those
- * unconfigured slave addresses
- *
- * @api
- */
-void i2cSlaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg);
-
-/**
- * @brief return @p I2CSlaveMsg for processing received messages
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @returns @p I2CSlaveMsg struct for processing subsequent messages
- *
- * @api
- */
-static inline
- const I2CSlaveMsg *i2cSlaveReceiveMsg(I2CDriver *i2cp)
-{
- osalDbgCheck(i2cp != NULL);
- return i2c_lld_get_slaveReceive(i2cp);
-}
-
-/**
- * @brief Configure callbacks & buffers for query reply
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries
- *
- * @details Must be called from a thread
- * Call i2cMatchAddress() after this to start processing
- * Enabling match addresses before installing handler callbacks can
- * result in locking the I2C bus when a master accesses those
- * unconfigured slave addresses
- *
- * @api
- */
-void i2cSlaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg);
-
-
-/**
- * @brief return @p I2CSlaveMsg for processing received messages
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @returns @p I2CSlaveMsg struct for processing subsequent messages
- *
- * @api
- */
-static inline
- const I2CSlaveMsg *i2cSlaveReplyMsg(I2CDriver *i2cp)
-/*
- processing descriptor for the next reply message
-*/
-{
- osalDbgCheck(i2cp != NULL);
- return i2c_lld_get_slaveReply(i2cp);
-}
-
-/**
- * @brief Configure callbacks & buffers for message reception
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages
- *
- * @details Must be called from an interrupt context
- *
- * @api
- */
-static inline void
- i2cSlaveReceiveI(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg)
-{
- osalDbgCheck(i2cp != NULL && rxMsg != NULL);
- i2c_lld_slaveReceive(i2cp, rxMsg);
-}
-
-/**
- * @brief Configure callbacks & buffers for query reply
- *
- * @param[in] i2cp pointer to the @p I2CDriver object
- * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent messages
- *
- * @details Must be called from an interrupt context
- *
- * @api
- */
-static inline void
- i2cSlaveReplyI(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg)
-/*
- Prepare to reply to I2C read requests from bus masters
- according to the replyMsg configuration.
-
- Notes:
- Must be called from interrupt context
- Does not affect the processing of any message reply being sent
-*/
-{
- osalDbgCheck(i2cp != NULL && replyMsg != NULL);
- i2c_lld_slaveReply(i2cp, replyMsg);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HAL_USE_I2C_SLAVE */
-
-#endif /* _I2CSLAVE_H_ */
diff --git a/lib/chibios b/lib/chibios
index 84a65901f0..c846437e39 160000
--- a/lib/chibios
+++ b/lib/chibios
@@ -1 +1 @@
-Subproject commit 84a65901f0d4784f10210637478c769e0ee6c415
+Subproject commit c846437e39423ef9394aecd3a96393db24c51ebf