mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2025-01-17 09:33:30 +08:00
ea6d73f140
1. Upgrade Cortex driver library (CMSIS -> CMSIS & Device): version 2.3.2 -> 3.0.1 & 3.0.0 - Remove "bsp/efm32/Libraries/CMSIS/Lib/ARM", "bsp/efm32/Libraries/CMSIS/Lib/G++" and "bsp/efm32/Libraries/CMSIS/SVD" to save space 2. Upgrade EFM32 driver libraries (efm32lib -> emlib): version 2.3.2 -> 3.0.0 - Remove "bsp/efm32/Libraries/Device/EnergyMicro/EFM32LG" and "bsp/efm32/Libraries/Device/EnergyMicro/EFM32TG" to save space 3. Upgrade EFM32GG_DK3750 development kit driver library: version 1.2.2 -> 2.0.1 4. Upgrade EFM32_Gxxx_DK development kit driver library: version 1.7.3 -> 2.0.1 5. Add energy management unit driver and test code 6. Modify linker script and related code to compatible with new version of libraries 7. Change EFM32 branch version number to 1.0 8. Add photo frame demo application git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2122 bbd45198-f89e-11dd-88c7-29a3b14d5316
489 lines
17 KiB
C
489 lines
17 KiB
C
/***************************************************************************//**
|
|
* @file
|
|
* @brief Inter-intergrated circuit (I2C) peripheral API
|
|
* @author Energy Micro AS
|
|
* @version 3.0.0
|
|
*******************************************************************************
|
|
* @section License
|
|
* <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.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: Energy Micro AS has no
|
|
* obligation to support this Software. Energy Micro AS 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.
|
|
*
|
|
* Energy Micro AS 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 <stdbool.h>
|
|
#include "em_part.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/***************************************************************************//**
|
|
* @addtogroup EM_Library
|
|
* @{
|
|
******************************************************************************/
|
|
|
|
/***************************************************************************//**
|
|
* @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
|
|
*/
|
|
#define I2C_FREQ_STANDARD_MAX 93500
|
|
|
|
/**
|
|
* @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 392500
|
|
|
|
|
|
/**
|
|
* @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.012us, 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 987500
|
|
|
|
|
|
/**
|
|
* @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 refFreq,
|
|
uint32_t freq,
|
|
I2C_ClockHLR_TypeDef type);
|
|
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
|
|
* 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 EM_Library) */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* __EM_I2C_H */
|