The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.
Dependents: hello SerialTestv11 SerialTestv12 Sierpinski ... more
mbed 2
This is the mbed 2 library. If you'd like to learn about Mbed OS please see the mbed-os docs.
Diff: TARGET_TB_SENSE_1/TOOLCHAIN_IAR/em_i2c.h
- Revision:
- 171:3a7713b1edbc
- Parent:
- 160:5571c4ff569f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TARGET_TB_SENSE_1/TOOLCHAIN_IAR/em_i2c.h Thu Nov 08 11:45:42 2018 +0000 @@ -0,0 +1,515 @@ +/***************************************************************************//** + * @file em_i2c.h + * @brief Inter-intergrated circuit (I2C) peripheral API + * @version 5.3.3 + ******************************************************************************* + * # License + * <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b> + ******************************************************************************* + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no + * obligation to support this Software. Silicon Labs is providing the + * Software "AS IS", with no express or implied warranties of any kind, + * including, but not limited to, any implied warranties of merchantability + * or fitness for any particular purpose or warranties against infringement + * of any proprietary rights of a third party. + * + * Silicon Labs will not be liable for any consequential, incidental, or + * special damages, or any other relief, or for any claim by any third party, + * arising from your use of this Software. + * + ******************************************************************************/ + +#ifndef EM_I2C_H +#define EM_I2C_H + +#include "em_device.h" +#if defined(I2C_COUNT) && (I2C_COUNT > 0) + +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************//** + * @addtogroup emlib + * @{ + ******************************************************************************/ + +/***************************************************************************//** + * @addtogroup I2C + * @{ + ******************************************************************************/ + +/******************************************************************************* + ******************************* DEFINES *********************************** + ******************************************************************************/ + +/** + * @brief + * Standard mode max frequency assuming using 4:4 ratio for Nlow:Nhigh. + * @details + * From I2C specification: Min Tlow = 4.7us, min Thigh = 4.0us, + * max Trise=1.0us, max Tfall=0.3us. Since ratio is 4:4, have to use + * worst case value of Tlow or Thigh as base. + * + * 1/(Tlow + Thigh + 1us + 0.3us) = 1/(4.7 + 4.7 + 1.3)us = 93458Hz + * @note + * Due to chip characteristics, the max value is somewhat reduced. + */ +#if defined(_SILICON_LABS_32B_SERIES_0) \ + && (defined(_EFM32_GECKO_FAMILY) \ + || defined(_EFM32_TINY_FAMILY) \ + || defined(_EFM32_ZERO_FAMILY) \ + || defined(_EFM32_HAPPY_FAMILY)) +#define I2C_FREQ_STANDARD_MAX 93000 +#elif defined(_SILICON_LABS_32B_SERIES_0) \ + && (defined(_EFM32_GIANT_FAMILY) \ + || defined(_EFM32_WONDER_FAMILY)) +#define I2C_FREQ_STANDARD_MAX 92000 +#elif defined(_SILICON_LABS_32B_SERIES_1) +// None of the chips on this platform has been characterized on this parameter. +// Use same value as on Wonder until further notice. +#define I2C_FREQ_STANDARD_MAX 92000 +#else +#error "Unknown device family." +#endif + +/** + * @brief + * Fast mode max frequency assuming using 6:3 ratio for Nlow:Nhigh. + * @details + * From I2C specification: Min Tlow = 1.3us, min Thigh = 0.6us, + * max Trise=0.3us, max Tfall=0.3us. Since ratio is 6:3, have to use + * worst case value of Tlow or 2xThigh as base. + * + * 1/(Tlow + Thigh + 0.3us + 0.3us) = 1/(1.3 + 0.65 + 0.6)us = 392157Hz + */ +#define I2C_FREQ_FAST_MAX 392157 + +/** + * @brief + * Fast mode+ max frequency assuming using 11:6 ratio for Nlow:Nhigh. + * @details + * From I2C specification: Min Tlow = 0.5us, min Thigh = 0.26us, + * max Trise=0.12us, max Tfall=0.12us. Since ratio is 11:6, have to use + * worst case value of Tlow or (11/6)xThigh as base. + * + * 1/(Tlow + Thigh + 0.12us + 0.12us) = 1/(0.5 + 0.273 + 0.24)us = 987167Hz + */ +#define I2C_FREQ_FASTPLUS_MAX 987167 + +/** + * @brief + * Indicate plain write sequence: S+ADDR(W)+DATA0+P. + * @details + * @li S - Start + * @li ADDR(W) - address with W/R bit cleared + * @li DATA0 - Data taken from buffer with index 0 + * @li P - Stop + */ +#define I2C_FLAG_WRITE 0x0001 + +/** + * @brief + * Indicate plain read sequence: S+ADDR(R)+DATA0+P. + * @details + * @li S - Start + * @li ADDR(R) - address with W/R bit set + * @li DATA0 - Data read into buffer with index 0 + * @li P - Stop + */ +#define I2C_FLAG_READ 0x0002 + +/** + * @brief + * Indicate combined write/read sequence: S+ADDR(W)+DATA0+Sr+ADDR(R)+DATA1+P. + * @details + * @li S - Start + * @li Sr - Repeated start + * @li ADDR(W) - address with W/R bit cleared + * @li ADDR(R) - address with W/R bit set + * @li DATAn - Data written from/read into buffer with index n + * @li P - Stop + */ +#define I2C_FLAG_WRITE_READ 0x0004 + +/** + * @brief + * Indicate write sequence using two buffers: S+ADDR(W)+DATA0+DATA1+P. + * @details + * @li S - Start + * @li ADDR(W) - address with W/R bit cleared + * @li DATAn - Data written from buffer with index n + * @li P - Stop + */ +#define I2C_FLAG_WRITE_WRITE 0x0008 + +/** Use 10 bit address. */ +#define I2C_FLAG_10BIT_ADDR 0x0010 + +/******************************************************************************* + ******************************** ENUMS ************************************ + ******************************************************************************/ + +/** Clock low to high ratio settings. */ +typedef enum { + i2cClockHLRStandard = _I2C_CTRL_CLHR_STANDARD, /**< Ratio is 4:4 */ + i2cClockHLRAsymetric = _I2C_CTRL_CLHR_ASYMMETRIC, /**< Ratio is 6:3 */ + i2cClockHLRFast = _I2C_CTRL_CLHR_FAST /**< Ratio is 11:3 */ +} I2C_ClockHLR_TypeDef; + +/** Return codes for single master mode transfer function. */ +typedef enum { + /* In progress code (>0) */ + i2cTransferInProgress = 1, /**< Transfer in progress. */ + + /* Complete code (=0) */ + i2cTransferDone = 0, /**< Transfer completed successfully. */ + + /* Transfer error codes (<0) */ + i2cTransferNack = -1, /**< NACK received during transfer. */ + i2cTransferBusErr = -2, /**< Bus error during transfer (misplaced START/STOP). */ + i2cTransferArbLost = -3, /**< Arbitration lost during transfer. */ + i2cTransferUsageFault = -4, /**< Usage fault. */ + i2cTransferSwFault = -5 /**< SW fault. */ +} I2C_TransferReturn_TypeDef; + +/******************************************************************************* + ******************************* STRUCTS *********************************** + ******************************************************************************/ + +/** I2C initialization structure. */ +typedef struct { + /** Enable I2C peripheral when init completed. */ + bool enable; + + /** Set to master (true) or slave (false) mode */ + bool master; + + /** + * I2C reference clock assumed when configuring bus frequency setup. + * Set it to 0 if currently configurated reference clock shall be used + * This parameter is only applicable if operating in master mode. + */ + uint32_t refFreq; + + /** + * (Max) I2C bus frequency to use. This parameter is only applicable + * if operating in master mode. + */ + uint32_t freq; + + /** Clock low/high ratio control. */ + I2C_ClockHLR_TypeDef clhr; +} I2C_Init_TypeDef; + +/** Suggested default config for I2C init structure. */ +#define I2C_INIT_DEFAULT \ + { \ + true, /* Enable when init done */ \ + true, /* Set to master mode */ \ + 0, /* Use currently configured reference clock */ \ + I2C_FREQ_STANDARD_MAX, /* Set to standard rate assuring being */ \ + /* within I2C spec */ \ + i2cClockHLRStandard /* Set to use 4:4 low/high duty cycle */ \ + } + +/** + * @brief + * Master mode transfer message structure used to define a complete + * I2C transfer sequence (from start to stop). + * @details + * The structure allows for defining the following types of sequences, + * please refer to defines for sequence details. + * @li #I2C_FLAG_READ - data read into buf[0].data + * @li #I2C_FLAG_WRITE - data written from buf[0].data + * @li #I2C_FLAG_WRITE_READ - data written from buf[0].data and read + * into buf[1].data + * @li #I2C_FLAG_WRITE_WRITE - data written from buf[0].data and + * buf[1].data + */ +typedef struct { + /** + * @brief + * Address to use after (repeated) start. + * @details + * Layout details, A = address bit, X = don't care bit (set to 0): + * @li 7 bit address - use format AAAA AAAX. + * @li 10 bit address - use format XXXX XAAX AAAA AAAA + */ + uint16_t addr; + + /** Flags defining sequence type and details, see I2C_FLAG_... defines. */ + uint16_t flags; + + /** + * Buffers used to hold data to send from or receive into depending + * on sequence type. + */ + struct { + /** Buffer used for data to transmit/receive, must be @p len long. */ + uint8_t *data; + + /** + * Number of bytes in @p data to send or receive. Notice that when + * receiving data to this buffer, at least 1 byte must be received. + * Setting @p len to 0 in the receive case is considered a usage fault. + * Transmitting 0 bytes is legal, in which case only the address + * is transmitted after the start condition. + */ + uint16_t len; + } buf[2]; +} I2C_TransferSeq_TypeDef; + +/******************************************************************************* + ***************************** PROTOTYPES ********************************** + ******************************************************************************/ + +uint32_t I2C_BusFreqGet(I2C_TypeDef *i2c); +void I2C_BusFreqSet(I2C_TypeDef *i2c, + uint32_t freqRef, + uint32_t freqScl, + I2C_ClockHLR_TypeDef i2cMode); +void I2C_Enable(I2C_TypeDef *i2c, bool enable); +void I2C_Init(I2C_TypeDef *i2c, const I2C_Init_TypeDef *init); + +/***************************************************************************//** + * @brief + * Clear one or more pending I2C interrupts. + * + * @param[in] i2c + * Pointer to I2C peripheral register block. + * + * @param[in] flags + * Pending I2C interrupt source to clear. Use a bitwse logic OR combination of + * valid interrupt flags for the I2C module (I2C_IF_nnn). + ******************************************************************************/ +__STATIC_INLINE void I2C_IntClear(I2C_TypeDef *i2c, uint32_t flags) +{ + i2c->IFC = flags; +} + +/***************************************************************************//** + * @brief + * Disable one or more I2C interrupts. + * + * @param[in] i2c + * Pointer to I2C peripheral register block. + * + * @param[in] flags + * I2C interrupt sources to disable. Use a bitwise logic OR combination of + * valid interrupt flags for the I2C module (I2C_IF_nnn). + ******************************************************************************/ +__STATIC_INLINE void I2C_IntDisable(I2C_TypeDef *i2c, uint32_t flags) +{ + i2c->IEN &= ~(flags); +} + +/***************************************************************************//** + * @brief + * Enable one or more I2C interrupts. + * + * @note + * Depending on the use, a pending interrupt may already be set prior to + * enabling the interrupt. Consider using I2C_IntClear() prior to enabling + * if such a pending interrupt should be ignored. + * + * @param[in] i2c + * Pointer to I2C peripheral register block. + * + * @param[in] flags + * I2C interrupt sources to enable. Use a bitwise logic OR combination of + * valid interrupt flags for the I2C module (I2C_IF_nnn). + ******************************************************************************/ +__STATIC_INLINE void I2C_IntEnable(I2C_TypeDef *i2c, uint32_t flags) +{ + i2c->IEN |= flags; +} + +/***************************************************************************//** + * @brief + * Get pending I2C interrupt flags. + * + * @note + * The event bits are not cleared by the use of this function. + * + * @param[in] i2c + * Pointer to I2C peripheral register block. + * + * @return + * I2C interrupt sources pending. A bitwise logic OR combination of valid + * interrupt flags for the I2C module (I2C_IF_nnn). + ******************************************************************************/ +__STATIC_INLINE uint32_t I2C_IntGet(I2C_TypeDef *i2c) +{ + return i2c->IF; +} + +/***************************************************************************//** + * @brief + * Get enabled and pending I2C interrupt flags. + * Useful for handling more interrupt sources in the same interrupt handler. + * + * @note + * Interrupt flags are not cleared by the use of this function. + * + * @param[in] i2c + * Pointer to I2C peripheral register block. + * + * @return + * Pending and enabled I2C interrupt sources + * The return value is the bitwise AND of + * - the enabled interrupt sources in I2Cn_IEN and + * - the pending interrupt flags I2Cn_IF + ******************************************************************************/ +__STATIC_INLINE uint32_t I2C_IntGetEnabled(I2C_TypeDef *i2c) +{ + uint32_t ien; + + ien = i2c->IEN; + return i2c->IF & ien; +} + +/***************************************************************************//** + * @brief + * Set one or more pending I2C interrupts from SW. + * + * @param[in] i2c + * Pointer to I2C peripheral register block. + * + * @param[in] flags + * I2C interrupt sources to set to pending. Use a bitwise logic OR combination + * of valid interrupt flags for the I2C module (I2C_IF_nnn). + ******************************************************************************/ +__STATIC_INLINE void I2C_IntSet(I2C_TypeDef *i2c, uint32_t flags) +{ + i2c->IFS = flags; +} + +void I2C_Reset(I2C_TypeDef *i2c); + +/***************************************************************************//** + * @brief + * Get slave address used for I2C peripheral (when operating in slave mode). + * + * @details + * For 10 bit addressing mode, the address is split in two bytes, and only + * the first byte setting is fetched, effectively only controlling the 2 most + * significant bits of the 10 bit address. Full handling of 10 bit addressing + * in slave mode requires additional SW handling. + * + * @param[in] i2c + * Pointer to I2C peripheral register block. + * + * @return + * I2C slave address in use. The 7 most significant bits define the actual + * address, the least significant bit is reserved and always returned as 0. + ******************************************************************************/ +__STATIC_INLINE uint8_t I2C_SlaveAddressGet(I2C_TypeDef *i2c) +{ + return ((uint8_t)(i2c->SADDR)); +} + +/***************************************************************************//** + * @brief + * Set slave address to use for I2C peripheral (when operating in slave mode). + * + * @details + * For 10 bit addressing mode, the address is split in two bytes, and only + * the first byte is set, effectively only controlling the 2 most significant + * bits of the 10 bit address. Full handling of 10 bit addressing in slave + * mode requires additional SW handling. + * + * @param[in] i2c + * Pointer to I2C peripheral register block. + * + * @param[in] addr + * I2C slave address to use. The 7 most significant bits define the actual + * address, the least significant bit is reserved and always set to 0. + ******************************************************************************/ +__STATIC_INLINE void I2C_SlaveAddressSet(I2C_TypeDef *i2c, uint8_t addr) +{ + i2c->SADDR = (uint32_t)addr & 0xfe; +} + +/***************************************************************************//** + * @brief + * Get slave address mask used for I2C peripheral (when operating in slave + * mode). + * + * @details + * The address mask defines how the comparator works. A bit position with + * value 0 means that the corresponding slave address bit is ignored during + * comparison (don't care). A bit position with value 1 means that the + * corresponding slave address bit must match. + * + * For 10 bit addressing mode, the address is split in two bytes, and only + * the mask for the first address byte is fetched, effectively only + * controlling the 2 most significant bits of the 10 bit address. + * + * @param[in] i2c + * Pointer to I2C peripheral register block. + * + * @return + * I2C slave address mask in use. The 7 most significant bits define the + * actual address mask, the least significant bit is reserved and always + * returned as 0. + ******************************************************************************/ +__STATIC_INLINE uint8_t I2C_SlaveAddressMaskGet(I2C_TypeDef *i2c) +{ + return ((uint8_t)(i2c->SADDRMASK)); +} + +/***************************************************************************//** + * @brief + * Set slave address mask used for I2C peripheral (when operating in slave + * mode). + * + * @details + * The address mask defines how the comparator works. A bit position with + * value 0 means that the corresponding slave address bit is ignored during + * comparison (don't care). A bit position with value 1 means that the + * corresponding slave address bit must match. + * + * For 10 bit addressing mode, the address is split in two bytes, and only + * the mask for the first address byte is set, effectively only controlling + * the 2 most significant bits of the 10 bit address. + * + * @param[in] i2c + * Pointer to I2C peripheral register block. + * + * @param[in] mask + * I2C slave address mask to use. The 7 most significant bits define the + * actual address mask, the least significant bit is reserved and should + * be 0. + ******************************************************************************/ +__STATIC_INLINE void I2C_SlaveAddressMaskSet(I2C_TypeDef *i2c, uint8_t mask) +{ + i2c->SADDRMASK = (uint32_t)mask & 0xfe; +} + +I2C_TransferReturn_TypeDef I2C_Transfer(I2C_TypeDef *i2c); +I2C_TransferReturn_TypeDef I2C_TransferInit(I2C_TypeDef *i2c, + I2C_TransferSeq_TypeDef *seq); + +/** @} (end addtogroup I2C) */ +/** @} (end addtogroup emlib) */ + +#ifdef __cplusplus +} +#endif + +#endif /* defined(I2C_COUNT) && (I2C_COUNT > 0) */ +#endif /* EM_I2C_H */