@ -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 |
@ -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_ */ | |||||
/** @} */ |
@ -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 |
@ -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_ */ | |||||
/** @} */ |
@ -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 */ | |||||
/** @} */ |
@ -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_ */ | |||||
/** @} */ |
@ -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 <http://www.gnu.org/licenses/>. | |||||
--- | |||||
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 <hal_i2c.h> | |||||
#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_ */ |
@ -1 +1 @@ | |||||
Subproject commit 84a65901f0d4784f10210637478c769e0ee6c415 | |||||
Subproject commit c846437e39423ef9394aecd3a96393db24c51ebf |