added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Fri Sep 02 15:07:44 2016 +0100
Revision:
144:ef7eb2e8f9f7
Parent:
50:a417edff4437
This updates the lib to the mbed lib v125

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 2 * @file em_i2c.c
<> 144:ef7eb2e8f9f7 3 * @brief Inter-integrated Circuit (I2C) Peripheral API
<> 144:ef7eb2e8f9f7 4 * @version 4.2.1
<> 144:ef7eb2e8f9f7 5 *******************************************************************************
<> 144:ef7eb2e8f9f7 6 * @section License
<> 144:ef7eb2e8f9f7 7 * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
<> 144:ef7eb2e8f9f7 8 *******************************************************************************
<> 144:ef7eb2e8f9f7 9 *
<> 144:ef7eb2e8f9f7 10 * Permission is granted to anyone to use this software for any purpose,
<> 144:ef7eb2e8f9f7 11 * including commercial applications, and to alter it and redistribute it
<> 144:ef7eb2e8f9f7 12 * freely, subject to the following restrictions:
<> 144:ef7eb2e8f9f7 13 *
<> 144:ef7eb2e8f9f7 14 * 1. The origin of this software must not be misrepresented; you must not
<> 144:ef7eb2e8f9f7 15 * claim that you wrote the original software.
<> 144:ef7eb2e8f9f7 16 * 2. Altered source versions must be plainly marked as such, and must not be
<> 144:ef7eb2e8f9f7 17 * misrepresented as being the original software.
<> 144:ef7eb2e8f9f7 18 * 3. This notice may not be removed or altered from any source distribution.
<> 144:ef7eb2e8f9f7 19 *
<> 144:ef7eb2e8f9f7 20 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
<> 144:ef7eb2e8f9f7 21 * obligation to support this Software. Silicon Labs is providing the
<> 144:ef7eb2e8f9f7 22 * Software "AS IS", with no express or implied warranties of any kind,
<> 144:ef7eb2e8f9f7 23 * including, but not limited to, any implied warranties of merchantability
<> 144:ef7eb2e8f9f7 24 * or fitness for any particular purpose or warranties against infringement
<> 144:ef7eb2e8f9f7 25 * of any proprietary rights of a third party.
<> 144:ef7eb2e8f9f7 26 *
<> 144:ef7eb2e8f9f7 27 * Silicon Labs will not be liable for any consequential, incidental, or
<> 144:ef7eb2e8f9f7 28 * special damages, or any other relief, or for any claim by any third party,
<> 144:ef7eb2e8f9f7 29 * arising from your use of this Software.
<> 144:ef7eb2e8f9f7 30 *
<> 144:ef7eb2e8f9f7 31 ******************************************************************************/
<> 144:ef7eb2e8f9f7 32
<> 144:ef7eb2e8f9f7 33 #include "em_i2c.h"
<> 144:ef7eb2e8f9f7 34 #if defined(I2C_COUNT) && (I2C_COUNT > 0)
<> 144:ef7eb2e8f9f7 35
<> 144:ef7eb2e8f9f7 36 #include "em_cmu.h"
<> 144:ef7eb2e8f9f7 37 #include "em_bus.h"
<> 144:ef7eb2e8f9f7 38 #include "em_assert.h"
<> 144:ef7eb2e8f9f7 39
<> 144:ef7eb2e8f9f7 40 #include <limits.h>
<> 144:ef7eb2e8f9f7 41
<> 144:ef7eb2e8f9f7 42 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 43 * @addtogroup EM_Library
<> 144:ef7eb2e8f9f7 44 * @{
<> 144:ef7eb2e8f9f7 45 ******************************************************************************/
<> 144:ef7eb2e8f9f7 46
<> 144:ef7eb2e8f9f7 47 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 48 * @addtogroup I2C
<> 144:ef7eb2e8f9f7 49 * @brief Inter-integrated Circuit (I2C) Peripheral API
<> 144:ef7eb2e8f9f7 50 * @{
<> 144:ef7eb2e8f9f7 51 ******************************************************************************/
<> 144:ef7eb2e8f9f7 52
<> 144:ef7eb2e8f9f7 53 /*******************************************************************************
<> 144:ef7eb2e8f9f7 54 ******************************* DEFINES ***********************************
<> 144:ef7eb2e8f9f7 55 ******************************************************************************/
<> 144:ef7eb2e8f9f7 56
<> 144:ef7eb2e8f9f7 57 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
<> 144:ef7eb2e8f9f7 58
<> 144:ef7eb2e8f9f7 59 /** Validation of I2C register block pointer reference for assert statements. */
<> 144:ef7eb2e8f9f7 60 #if (I2C_COUNT == 1)
<> 144:ef7eb2e8f9f7 61 #define I2C_REF_VALID(ref) ((ref) == I2C0)
<> 144:ef7eb2e8f9f7 62 #elif (I2C_COUNT == 2)
<> 144:ef7eb2e8f9f7 63 #define I2C_REF_VALID(ref) ((ref == I2C0) || (ref == I2C1))
<> 144:ef7eb2e8f9f7 64 #elif (I2C_COUNT == 3)
<> 144:ef7eb2e8f9f7 65 #define I2C_REF_VALID(ref) ((ref == I2C0) || (ref == I2C1)|| (ref == I2C2))
<> 144:ef7eb2e8f9f7 66 #endif
<> 144:ef7eb2e8f9f7 67
<> 144:ef7eb2e8f9f7 68 /** Error flags indicating I2C transfer has failed somehow. */
<> 144:ef7eb2e8f9f7 69 /* Notice that I2C_IF_TXOF (transmit overflow) is not really possible with */
<> 144:ef7eb2e8f9f7 70 /* this SW supporting master mode. Likewise for I2C_IF_RXUF (receive underflow) */
<> 144:ef7eb2e8f9f7 71 /* RXUF is only likely to occur with this SW if using a debugger peeking into */
<> 144:ef7eb2e8f9f7 72 /* RXDATA register. Thus, we ignore those types of fault. */
<> 144:ef7eb2e8f9f7 73 #define I2C_IF_ERRORS (I2C_IF_BUSERR | I2C_IF_ARBLOST)
<> 144:ef7eb2e8f9f7 74
<> 144:ef7eb2e8f9f7 75 /* Max I2C transmission rate constant */
<> 144:ef7eb2e8f9f7 76 #if defined( _SILICON_LABS_32B_PLATFORM_1 )
<> 144:ef7eb2e8f9f7 77 #define I2C_CR_MAX 4
<> 144:ef7eb2e8f9f7 78 #elif defined( _SILICON_LABS_32B_PLATFORM_2 )
<> 144:ef7eb2e8f9f7 79 #define I2C_CR_MAX 8
<> 144:ef7eb2e8f9f7 80 #else
<> 144:ef7eb2e8f9f7 81 #warning "Max I2C transmission rate constant is not defined"
<> 144:ef7eb2e8f9f7 82 #endif
<> 144:ef7eb2e8f9f7 83
<> 144:ef7eb2e8f9f7 84 /** @endcond */
<> 144:ef7eb2e8f9f7 85
<> 144:ef7eb2e8f9f7 86 /*******************************************************************************
<> 144:ef7eb2e8f9f7 87 ******************************** ENUMS ************************************
<> 144:ef7eb2e8f9f7 88 ******************************************************************************/
<> 144:ef7eb2e8f9f7 89
<> 144:ef7eb2e8f9f7 90 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
<> 144:ef7eb2e8f9f7 91
<> 144:ef7eb2e8f9f7 92 /** Master mode transfer states. */
<> 144:ef7eb2e8f9f7 93 typedef enum
<> 144:ef7eb2e8f9f7 94 {
<> 144:ef7eb2e8f9f7 95 i2cStateStartAddrSend, /**< Send start + (first part of) address. */
<> 144:ef7eb2e8f9f7 96 i2cStateAddrWFAckNack, /**< Wait for ACK/NACK on (first part of) address. */
<> 144:ef7eb2e8f9f7 97 i2cStateAddrWF2ndAckNack, /**< Wait for ACK/NACK on second part of 10 bit address. */
<> 144:ef7eb2e8f9f7 98 i2cStateRStartAddrSend, /**< Send repeated start + (first part of) address. */
<> 144:ef7eb2e8f9f7 99 i2cStateRAddrWFAckNack, /**< Wait for ACK/NACK on address sent after repeated start. */
<> 144:ef7eb2e8f9f7 100 i2cStateDataSend, /**< Send data. */
<> 144:ef7eb2e8f9f7 101 i2cStateDataWFAckNack, /**< Wait for ACK/NACK on data sent. */
<> 144:ef7eb2e8f9f7 102 i2cStateWFData, /**< Wait for data. */
<> 144:ef7eb2e8f9f7 103 i2cStateWFStopSent, /**< Wait for STOP to have been transmitted. */
<> 144:ef7eb2e8f9f7 104 i2cStateDone /**< Transfer completed successfully. */
<> 144:ef7eb2e8f9f7 105 } I2C_TransferState_TypeDef;
<> 144:ef7eb2e8f9f7 106
<> 144:ef7eb2e8f9f7 107 /** @endcond */
<> 144:ef7eb2e8f9f7 108
<> 144:ef7eb2e8f9f7 109 /*******************************************************************************
<> 144:ef7eb2e8f9f7 110 ******************************* STRUCTS ***********************************
<> 144:ef7eb2e8f9f7 111 ******************************************************************************/
<> 144:ef7eb2e8f9f7 112
<> 144:ef7eb2e8f9f7 113 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
<> 144:ef7eb2e8f9f7 114
<> 144:ef7eb2e8f9f7 115 /** Structure used to store state information on an ongoing master mode transfer. */
<> 144:ef7eb2e8f9f7 116 typedef struct
<> 144:ef7eb2e8f9f7 117 {
<> 144:ef7eb2e8f9f7 118 /** Current state. */
<> 144:ef7eb2e8f9f7 119 I2C_TransferState_TypeDef state;
<> 144:ef7eb2e8f9f7 120
<> 144:ef7eb2e8f9f7 121 /** Result return code. */
<> 144:ef7eb2e8f9f7 122 I2C_TransferReturn_TypeDef result;
<> 144:ef7eb2e8f9f7 123
<> 144:ef7eb2e8f9f7 124 /** Offset in current sequence buffer. */
<> 144:ef7eb2e8f9f7 125 uint16_t offset;
<> 144:ef7eb2e8f9f7 126
<> 144:ef7eb2e8f9f7 127 /* Index to current sequence buffer in use. */
<> 144:ef7eb2e8f9f7 128 uint8_t bufIndx;
<> 144:ef7eb2e8f9f7 129
<> 144:ef7eb2e8f9f7 130 /** Reference to I2C transfer sequence definition provided by user. */
<> 144:ef7eb2e8f9f7 131 I2C_TransferSeq_TypeDef *seq;
<> 144:ef7eb2e8f9f7 132 } I2C_Transfer_TypeDef;
<> 144:ef7eb2e8f9f7 133
<> 144:ef7eb2e8f9f7 134 /** @endcond */
<> 144:ef7eb2e8f9f7 135
<> 144:ef7eb2e8f9f7 136 /*******************************************************************************
<> 144:ef7eb2e8f9f7 137 ***************************** LOCAL DATA *******^**************************
<> 144:ef7eb2e8f9f7 138 ******************************************************************************/
<> 144:ef7eb2e8f9f7 139
<> 144:ef7eb2e8f9f7 140 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
<> 144:ef7eb2e8f9f7 141
<> 144:ef7eb2e8f9f7 142 /**
<> 144:ef7eb2e8f9f7 143 * Lookup table for Nlow + Nhigh setting defined by CLHR. Set undefined
<> 144:ef7eb2e8f9f7 144 * index (0x3) to reflect default setting just in case.
<> 144:ef7eb2e8f9f7 145 */
<> 144:ef7eb2e8f9f7 146 static const uint8_t i2cNSum[] = { 4 + 4, 6 + 3, 11 + 6, 4 + 4 };
<> 144:ef7eb2e8f9f7 147
<> 144:ef7eb2e8f9f7 148 /** Transfer state info for ongoing master mode transfer */
<> 144:ef7eb2e8f9f7 149 static I2C_Transfer_TypeDef i2cTransfer[I2C_COUNT];
<> 144:ef7eb2e8f9f7 150
<> 144:ef7eb2e8f9f7 151 /** @endcond */
<> 144:ef7eb2e8f9f7 152
<> 144:ef7eb2e8f9f7 153 /*******************************************************************************
<> 144:ef7eb2e8f9f7 154 ************************** GLOBAL FUNCTIONS *******************************
<> 144:ef7eb2e8f9f7 155 ******************************************************************************/
<> 144:ef7eb2e8f9f7 156
<> 144:ef7eb2e8f9f7 157 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 158 * @brief
<> 144:ef7eb2e8f9f7 159 * Get current configured I2C bus frequency.
<> 144:ef7eb2e8f9f7 160 *
<> 144:ef7eb2e8f9f7 161 * @details
<> 144:ef7eb2e8f9f7 162 * This frequency is only of relevance when acting as master.
<> 144:ef7eb2e8f9f7 163 *
<> 144:ef7eb2e8f9f7 164 * @param[in] i2c
<> 144:ef7eb2e8f9f7 165 * Pointer to I2C peripheral register block.
<> 144:ef7eb2e8f9f7 166 *
<> 144:ef7eb2e8f9f7 167 * @return
<> 144:ef7eb2e8f9f7 168 * Current I2C frequency in Hz.
<> 144:ef7eb2e8f9f7 169 ******************************************************************************/
<> 144:ef7eb2e8f9f7 170 uint32_t I2C_BusFreqGet(I2C_TypeDef *i2c)
<> 144:ef7eb2e8f9f7 171 {
<> 144:ef7eb2e8f9f7 172 uint32_t freqHfper;
<> 144:ef7eb2e8f9f7 173 uint32_t n;
<> 144:ef7eb2e8f9f7 174
<> 144:ef7eb2e8f9f7 175 /* Max frequency is given by freqScl = freqHfper/((Nlow + Nhigh)(DIV + 1) + I2C_CR_MAX)
<> 144:ef7eb2e8f9f7 176 * More details can be found in the reference manual,
<> 144:ef7eb2e8f9f7 177 * I2C Clock Generation chapter. */
<> 144:ef7eb2e8f9f7 178 freqHfper = CMU_ClockFreqGet(cmuClock_HFPER);
<> 144:ef7eb2e8f9f7 179 /* n = Nlow + Nhigh */
<> 144:ef7eb2e8f9f7 180 n = (uint32_t)(i2cNSum[(i2c->CTRL & _I2C_CTRL_CLHR_MASK) >> _I2C_CTRL_CLHR_SHIFT]);
<> 144:ef7eb2e8f9f7 181
<> 144:ef7eb2e8f9f7 182 return (freqHfper / ((n * (i2c->CLKDIV + 1)) + I2C_CR_MAX));
<> 144:ef7eb2e8f9f7 183 }
<> 144:ef7eb2e8f9f7 184
<> 144:ef7eb2e8f9f7 185
<> 144:ef7eb2e8f9f7 186 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 187 * @brief
<> 144:ef7eb2e8f9f7 188 * Set I2C bus frequency.
<> 144:ef7eb2e8f9f7 189 *
<> 144:ef7eb2e8f9f7 190 * @details
<> 144:ef7eb2e8f9f7 191 * The bus frequency is only of relevance when acting as a master. The bus
<> 144:ef7eb2e8f9f7 192 * frequency should not be set higher than the max frequency accepted by the
<> 144:ef7eb2e8f9f7 193 * slowest device on the bus.
<> 144:ef7eb2e8f9f7 194 *
<> 144:ef7eb2e8f9f7 195 * Notice that due to asymmetric requirements on low and high I2C clock
<> 144:ef7eb2e8f9f7 196 * cycles by the I2C specification, the actual max frequency allowed in order
<> 144:ef7eb2e8f9f7 197 * to comply with the specification may be somewhat lower than expected.
<> 144:ef7eb2e8f9f7 198 *
<> 144:ef7eb2e8f9f7 199 * Please refer to the reference manual, details on I2C clock generation,
<> 144:ef7eb2e8f9f7 200 * for max allowed theoretical frequencies for different modes.
<> 144:ef7eb2e8f9f7 201 *
<> 144:ef7eb2e8f9f7 202 * @param[in] i2c
<> 144:ef7eb2e8f9f7 203 * Pointer to I2C peripheral register block.
<> 144:ef7eb2e8f9f7 204 *
<> 144:ef7eb2e8f9f7 205 * @param[in] freqRef
<> 144:ef7eb2e8f9f7 206 * I2C reference clock frequency in Hz that will be used. If set to 0,
<> 144:ef7eb2e8f9f7 207 * then HFPER clock is used. Setting it to a higher than actual configured
<> 144:ef7eb2e8f9f7 208 * value only has the consequence of reducing the real I2C frequency.
<> 144:ef7eb2e8f9f7 209 *
<> 144:ef7eb2e8f9f7 210 * @param[in] freqScl
<> 144:ef7eb2e8f9f7 211 * Bus frequency to set (actual bus speed may be lower due to integer
<> 144:ef7eb2e8f9f7 212 * prescaling). Safe (according to I2C specification) max frequencies for
<> 144:ef7eb2e8f9f7 213 * standard, fast and fast+ modes are available using I2C_FREQ_ defines.
<> 144:ef7eb2e8f9f7 214 * (Using I2C_FREQ_ defines requires corresponding setting of @p type.)
<> 144:ef7eb2e8f9f7 215 * Slowest slave device on bus must always be considered.
<> 144:ef7eb2e8f9f7 216 *
<> 144:ef7eb2e8f9f7 217 * @param[in] i2cMode
<> 144:ef7eb2e8f9f7 218 * Clock low to high ratio type to use. If not using i2cClockHLRStandard,
<> 144:ef7eb2e8f9f7 219 * make sure all devices on the bus support the specified mode. Using a
<> 144:ef7eb2e8f9f7 220 * non-standard ratio is useful to achieve higher bus clock in fast and
<> 144:ef7eb2e8f9f7 221 * fast+ modes.
<> 144:ef7eb2e8f9f7 222 ******************************************************************************/
<> 144:ef7eb2e8f9f7 223 void I2C_BusFreqSet(I2C_TypeDef *i2c,
<> 144:ef7eb2e8f9f7 224 uint32_t freqRef,
<> 144:ef7eb2e8f9f7 225 uint32_t freqScl,
<> 144:ef7eb2e8f9f7 226 I2C_ClockHLR_TypeDef i2cMode)
<> 144:ef7eb2e8f9f7 227 {
<> 144:ef7eb2e8f9f7 228 uint32_t n, minFreq;
<> 144:ef7eb2e8f9f7 229 int32_t div;
<> 144:ef7eb2e8f9f7 230
<> 144:ef7eb2e8f9f7 231 /* Avoid divide by 0 */
<> 144:ef7eb2e8f9f7 232 EFM_ASSERT(freqScl);
<> 144:ef7eb2e8f9f7 233 if (!freqScl)
<> 144:ef7eb2e8f9f7 234 {
<> 144:ef7eb2e8f9f7 235 return;
<> 144:ef7eb2e8f9f7 236 }
<> 144:ef7eb2e8f9f7 237
<> 144:ef7eb2e8f9f7 238 /* Set the CLHR (clock low to high ratio). */
<> 144:ef7eb2e8f9f7 239 i2c->CTRL &= ~_I2C_CTRL_CLHR_MASK;
<> 144:ef7eb2e8f9f7 240 BUS_RegMaskedWrite(&i2c->CTRL,
<> 144:ef7eb2e8f9f7 241 _I2C_CTRL_CLHR_MASK,
<> 144:ef7eb2e8f9f7 242 i2cMode <<_I2C_CTRL_CLHR_SHIFT);
<> 144:ef7eb2e8f9f7 243
<> 144:ef7eb2e8f9f7 244 if (!freqRef)
<> 144:ef7eb2e8f9f7 245 {
<> 144:ef7eb2e8f9f7 246 freqRef = CMU_ClockFreqGet(cmuClock_HFPER);
<> 144:ef7eb2e8f9f7 247 }
<> 144:ef7eb2e8f9f7 248
<> 144:ef7eb2e8f9f7 249 /* Check minumum HF peripheral clock */
<> 144:ef7eb2e8f9f7 250 minFreq = UINT_MAX;
<> 144:ef7eb2e8f9f7 251 if (i2c->CTRL & I2C_CTRL_SLAVE)
<> 144:ef7eb2e8f9f7 252 {
<> 144:ef7eb2e8f9f7 253 switch(i2cMode)
<> 144:ef7eb2e8f9f7 254 {
<> 144:ef7eb2e8f9f7 255 case i2cClockHLRStandard:
<> 144:ef7eb2e8f9f7 256 #if defined( _SILICON_LABS_32B_PLATFORM_1 )
<> 144:ef7eb2e8f9f7 257 minFreq = 4200000; break;
<> 144:ef7eb2e8f9f7 258 #elif defined( _SILICON_LABS_32B_PLATFORM_2 )
<> 144:ef7eb2e8f9f7 259 minFreq = 2000000; break;
<> 144:ef7eb2e8f9f7 260 #endif
<> 144:ef7eb2e8f9f7 261 case i2cClockHLRAsymetric:
<> 144:ef7eb2e8f9f7 262 #if defined( _SILICON_LABS_32B_PLATFORM_1 )
<> 144:ef7eb2e8f9f7 263 minFreq = 11000000; break;
<> 144:ef7eb2e8f9f7 264 #elif defined( _SILICON_LABS_32B_PLATFORM_2 )
<> 144:ef7eb2e8f9f7 265 minFreq = 5000000; break;
<> 144:ef7eb2e8f9f7 266 #endif
<> 144:ef7eb2e8f9f7 267 case i2cClockHLRFast:
<> 144:ef7eb2e8f9f7 268 #if defined( _SILICON_LABS_32B_PLATFORM_1 )
<> 144:ef7eb2e8f9f7 269 minFreq = 24400000; break;
<> 144:ef7eb2e8f9f7 270 #elif defined( _SILICON_LABS_32B_PLATFORM_2 )
<> 144:ef7eb2e8f9f7 271 minFreq = 14000000; break;
<> 144:ef7eb2e8f9f7 272 #endif
<> 144:ef7eb2e8f9f7 273 }
<> 144:ef7eb2e8f9f7 274 }
<> 144:ef7eb2e8f9f7 275 else
<> 144:ef7eb2e8f9f7 276 {
<> 144:ef7eb2e8f9f7 277 /* For master mode, platform 1 and 2 share the same
<> 144:ef7eb2e8f9f7 278 min frequencies */
<> 144:ef7eb2e8f9f7 279 switch(i2cMode)
<> 144:ef7eb2e8f9f7 280 {
<> 144:ef7eb2e8f9f7 281 case i2cClockHLRStandard:
<> 144:ef7eb2e8f9f7 282 minFreq = 2000000; break;
<> 144:ef7eb2e8f9f7 283 case i2cClockHLRAsymetric:
<> 144:ef7eb2e8f9f7 284 minFreq = 9000000; break;
<> 144:ef7eb2e8f9f7 285 case i2cClockHLRFast:
<> 144:ef7eb2e8f9f7 286 minFreq = 20000000; break;
<> 144:ef7eb2e8f9f7 287 }
<> 144:ef7eb2e8f9f7 288 }
<> 144:ef7eb2e8f9f7 289
<> 144:ef7eb2e8f9f7 290 /* Frequency most be larger-than */
<> 144:ef7eb2e8f9f7 291 EFM_ASSERT(freqRef > minFreq);
<> 144:ef7eb2e8f9f7 292
<> 144:ef7eb2e8f9f7 293 /* SCL frequency is given by
<> 144:ef7eb2e8f9f7 294 * freqScl = freqRef/((Nlow + Nhigh) * (DIV + 1) + I2C_C_MAX)
<> 144:ef7eb2e8f9f7 295 *
<> 144:ef7eb2e8f9f7 296 * Thus
<> 144:ef7eb2e8f9f7 297 * DIV = ((freqRef - (I2C_C_MAX * freqScl))/((Nlow + Nhigh) * freqScl)) - 1
<> 144:ef7eb2e8f9f7 298 *
<> 144:ef7eb2e8f9f7 299 * More details can be found in the reference manual,
<> 144:ef7eb2e8f9f7 300 * I2C Clock Generation chapter. */
<> 144:ef7eb2e8f9f7 301
<> 144:ef7eb2e8f9f7 302 /* n = Nlow + Nhigh */
<> 144:ef7eb2e8f9f7 303 n = (uint32_t)(i2cNSum[i2cMode]);
<> 144:ef7eb2e8f9f7 304 div = ((freqRef - (I2C_CR_MAX * freqScl)) / (n * freqScl)) - 1;
<> 144:ef7eb2e8f9f7 305 EFM_ASSERT(div >= 0);
<> 144:ef7eb2e8f9f7 306 EFM_ASSERT((uint32_t)div <= _I2C_CLKDIV_DIV_MASK);
<> 144:ef7eb2e8f9f7 307
<> 144:ef7eb2e8f9f7 308 /* Clock divisor must be at least 1 in slave mode according to reference */
<> 144:ef7eb2e8f9f7 309 /* manual (in which case there is normally no need to set bus frequency). */
<> 144:ef7eb2e8f9f7 310 if ((i2c->CTRL & I2C_CTRL_SLAVE) && !div)
<> 144:ef7eb2e8f9f7 311 {
<> 144:ef7eb2e8f9f7 312 div = 1;
<> 144:ef7eb2e8f9f7 313 }
<> 144:ef7eb2e8f9f7 314 i2c->CLKDIV = (uint32_t)div;
<> 144:ef7eb2e8f9f7 315 }
<> 144:ef7eb2e8f9f7 316
<> 144:ef7eb2e8f9f7 317
<> 144:ef7eb2e8f9f7 318 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 319 * @brief
<> 144:ef7eb2e8f9f7 320 * Enable/disable I2C.
<> 144:ef7eb2e8f9f7 321 *
<> 144:ef7eb2e8f9f7 322 * @note
<> 144:ef7eb2e8f9f7 323 * After enabling the I2C (from being disabled), the I2C is in BUSY state.
<> 144:ef7eb2e8f9f7 324 *
<> 144:ef7eb2e8f9f7 325 * @param[in] i2c
<> 144:ef7eb2e8f9f7 326 * Pointer to I2C peripheral register block.
<> 144:ef7eb2e8f9f7 327 *
<> 144:ef7eb2e8f9f7 328 * @param[in] enable
<> 144:ef7eb2e8f9f7 329 * true to enable counting, false to disable.
<> 144:ef7eb2e8f9f7 330 ******************************************************************************/
<> 144:ef7eb2e8f9f7 331 void I2C_Enable(I2C_TypeDef *i2c, bool enable)
<> 144:ef7eb2e8f9f7 332 {
<> 144:ef7eb2e8f9f7 333 EFM_ASSERT(I2C_REF_VALID(i2c));
<> 144:ef7eb2e8f9f7 334
<> 144:ef7eb2e8f9f7 335 BUS_RegBitWrite(&(i2c->CTRL), _I2C_CTRL_EN_SHIFT, enable);
<> 144:ef7eb2e8f9f7 336 }
<> 144:ef7eb2e8f9f7 337
<> 144:ef7eb2e8f9f7 338
<> 144:ef7eb2e8f9f7 339 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 340 * @brief
<> 144:ef7eb2e8f9f7 341 * Initialize I2C.
<> 144:ef7eb2e8f9f7 342 *
<> 144:ef7eb2e8f9f7 343 * @param[in] i2c
<> 144:ef7eb2e8f9f7 344 * Pointer to I2C peripheral register block.
<> 144:ef7eb2e8f9f7 345 *
<> 144:ef7eb2e8f9f7 346 * @param[in] init
<> 144:ef7eb2e8f9f7 347 * Pointer to I2C initialization structure.
<> 144:ef7eb2e8f9f7 348 ******************************************************************************/
<> 144:ef7eb2e8f9f7 349 void I2C_Init(I2C_TypeDef *i2c, const I2C_Init_TypeDef *init)
<> 144:ef7eb2e8f9f7 350 {
<> 144:ef7eb2e8f9f7 351 EFM_ASSERT(I2C_REF_VALID(i2c));
<> 144:ef7eb2e8f9f7 352
<> 144:ef7eb2e8f9f7 353 i2c->IEN = 0;
<> 144:ef7eb2e8f9f7 354 i2c->IFC = _I2C_IFC_MASK;
<> 144:ef7eb2e8f9f7 355
<> 144:ef7eb2e8f9f7 356 /* Set SLAVE select mode */
<> 144:ef7eb2e8f9f7 357 BUS_RegBitWrite(&(i2c->CTRL), _I2C_CTRL_SLAVE_SHIFT, init->master ? 0 : 1);
<> 144:ef7eb2e8f9f7 358
<> 144:ef7eb2e8f9f7 359 I2C_BusFreqSet(i2c, init->refFreq, init->freq, init->clhr);
<> 144:ef7eb2e8f9f7 360
<> 144:ef7eb2e8f9f7 361 BUS_RegBitWrite(&(i2c->CTRL), _I2C_CTRL_EN_SHIFT, init->enable);
<> 144:ef7eb2e8f9f7 362 }
<> 144:ef7eb2e8f9f7 363
<> 144:ef7eb2e8f9f7 364
<> 144:ef7eb2e8f9f7 365 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 366 * @brief
<> 144:ef7eb2e8f9f7 367 * Reset I2C to same state as after a HW reset.
<> 144:ef7eb2e8f9f7 368 *
<> 144:ef7eb2e8f9f7 369 * @note
<> 144:ef7eb2e8f9f7 370 * The ROUTE register is NOT reset by this function, in order to allow for
<> 144:ef7eb2e8f9f7 371 * centralized setup of this feature.
<> 144:ef7eb2e8f9f7 372 *
<> 144:ef7eb2e8f9f7 373 * @param[in] i2c
<> 144:ef7eb2e8f9f7 374 * Pointer to I2C peripheral register block.
<> 144:ef7eb2e8f9f7 375 ******************************************************************************/
<> 144:ef7eb2e8f9f7 376 void I2C_Reset(I2C_TypeDef *i2c)
<> 144:ef7eb2e8f9f7 377 {
<> 144:ef7eb2e8f9f7 378 i2c->CTRL = _I2C_CTRL_RESETVALUE;
<> 144:ef7eb2e8f9f7 379 i2c->CLKDIV = _I2C_CLKDIV_RESETVALUE;
<> 144:ef7eb2e8f9f7 380 i2c->SADDR = _I2C_SADDR_RESETVALUE;
<> 144:ef7eb2e8f9f7 381 i2c->SADDRMASK = _I2C_SADDRMASK_RESETVALUE;
<> 144:ef7eb2e8f9f7 382 i2c->IEN = _I2C_IEN_RESETVALUE;
<> 144:ef7eb2e8f9f7 383 i2c->IFC = _I2C_IFC_MASK;
<> 144:ef7eb2e8f9f7 384 /* Do not reset route register, setting should be done independently */
<> 144:ef7eb2e8f9f7 385 }
<> 144:ef7eb2e8f9f7 386
<> 144:ef7eb2e8f9f7 387
<> 144:ef7eb2e8f9f7 388 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 389 * @brief
<> 144:ef7eb2e8f9f7 390 * Continue an initiated I2C transfer (single master mode only).
<> 144:ef7eb2e8f9f7 391 *
<> 144:ef7eb2e8f9f7 392 * @details
<> 144:ef7eb2e8f9f7 393 * This function is used repeatedly after a I2C_TransferInit() in order to
<> 144:ef7eb2e8f9f7 394 * complete a transfer. It may be used in polled mode as the below example
<> 144:ef7eb2e8f9f7 395 * shows:
<> 144:ef7eb2e8f9f7 396 * @verbatim
<> 144:ef7eb2e8f9f7 397 * I2C_TransferReturn_TypeDef ret;
<> 144:ef7eb2e8f9f7 398 *
<> 144:ef7eb2e8f9f7 399 * // Do a polled transfer
<> 144:ef7eb2e8f9f7 400 * ret = I2C_TransferInit(I2C0, seq);
<> 144:ef7eb2e8f9f7 401 * while (ret == i2cTransferInProgress)
<> 144:ef7eb2e8f9f7 402 * {
<> 144:ef7eb2e8f9f7 403 * ret = I2C_Transfer(I2C0);
<> 144:ef7eb2e8f9f7 404 * }
<> 144:ef7eb2e8f9f7 405 * @endverbatim
<> 144:ef7eb2e8f9f7 406 * It may also be used in interrupt driven mode, where this function is invoked
<> 144:ef7eb2e8f9f7 407 * from the interrupt handler. Notice that if used in interrupt mode, NVIC
<> 144:ef7eb2e8f9f7 408 * interrupts must be configured and enabled for the I2C bus used. I2C
<> 144:ef7eb2e8f9f7 409 * peripheral specific interrupts are managed by this SW.
<> 144:ef7eb2e8f9f7 410 *
<> 144:ef7eb2e8f9f7 411 * @note
<> 144:ef7eb2e8f9f7 412 * Only single master mode is supported.
<> 144:ef7eb2e8f9f7 413 *
<> 144:ef7eb2e8f9f7 414 * @param[in] i2c
<> 144:ef7eb2e8f9f7 415 * Pointer to I2C peripheral register block.
<> 144:ef7eb2e8f9f7 416 *
<> 144:ef7eb2e8f9f7 417 * @return
<> 144:ef7eb2e8f9f7 418 * Returns status for ongoing transfer.
<> 144:ef7eb2e8f9f7 419 * @li #i2cTransferInProgress - indicates that transfer not finished.
<> 144:ef7eb2e8f9f7 420 * @li #i2cTransferDone - transfer completed successfully.
<> 144:ef7eb2e8f9f7 421 * @li otherwise some sort of error has occurred.
<> 144:ef7eb2e8f9f7 422 *
<> 144:ef7eb2e8f9f7 423 ******************************************************************************/
<> 144:ef7eb2e8f9f7 424 I2C_TransferReturn_TypeDef I2C_Transfer(I2C_TypeDef *i2c)
<> 144:ef7eb2e8f9f7 425 {
<> 144:ef7eb2e8f9f7 426 uint32_t tmp;
<> 144:ef7eb2e8f9f7 427 uint32_t pending;
<> 144:ef7eb2e8f9f7 428 I2C_Transfer_TypeDef *transfer;
<> 144:ef7eb2e8f9f7 429 I2C_TransferSeq_TypeDef *seq;
<> 144:ef7eb2e8f9f7 430
<> 144:ef7eb2e8f9f7 431 EFM_ASSERT(I2C_REF_VALID(i2c));
<> 144:ef7eb2e8f9f7 432
<> 144:ef7eb2e8f9f7 433 /* Support up to 2 I2C buses */
<> 144:ef7eb2e8f9f7 434 if (i2c == I2C0)
<> 144:ef7eb2e8f9f7 435 {
<> 144:ef7eb2e8f9f7 436 transfer = i2cTransfer;
<> 144:ef7eb2e8f9f7 437 }
<> 144:ef7eb2e8f9f7 438 #if (I2C_COUNT > 1)
<> 144:ef7eb2e8f9f7 439 else if (i2c == I2C1)
<> 144:ef7eb2e8f9f7 440 {
<> 144:ef7eb2e8f9f7 441 transfer = i2cTransfer + 1;
<> 144:ef7eb2e8f9f7 442 }
<> 144:ef7eb2e8f9f7 443 #endif
<> 144:ef7eb2e8f9f7 444 else
<> 144:ef7eb2e8f9f7 445 {
<> 144:ef7eb2e8f9f7 446 return i2cTransferUsageFault;
<> 144:ef7eb2e8f9f7 447 }
<> 144:ef7eb2e8f9f7 448
<> 144:ef7eb2e8f9f7 449 seq = transfer->seq;
<> 144:ef7eb2e8f9f7 450 for (;; )
<> 144:ef7eb2e8f9f7 451 {
<> 144:ef7eb2e8f9f7 452 pending = i2c->IF;
<> 144:ef7eb2e8f9f7 453
<> 144:ef7eb2e8f9f7 454 /* If some sort of fault, abort transfer. */
<> 144:ef7eb2e8f9f7 455 if (pending & I2C_IF_ERRORS)
<> 144:ef7eb2e8f9f7 456 {
<> 144:ef7eb2e8f9f7 457 if (pending & I2C_IF_ARBLOST)
<> 144:ef7eb2e8f9f7 458 {
<> 144:ef7eb2e8f9f7 459 /* If arbitration fault, it indicates either a slave device */
<> 144:ef7eb2e8f9f7 460 /* not responding as expected, or other master which is not */
<> 144:ef7eb2e8f9f7 461 /* supported by this SW. */
<> 144:ef7eb2e8f9f7 462 transfer->result = i2cTransferArbLost;
<> 144:ef7eb2e8f9f7 463 }
<> 144:ef7eb2e8f9f7 464 else if (pending & I2C_IF_BUSERR)
<> 144:ef7eb2e8f9f7 465 {
<> 144:ef7eb2e8f9f7 466 /* A bus error indicates a misplaced start or stop, which should */
<> 144:ef7eb2e8f9f7 467 /* not occur in master mode controlled by this SW. */
<> 144:ef7eb2e8f9f7 468 transfer->result = i2cTransferBusErr;
<> 144:ef7eb2e8f9f7 469 }
<> 144:ef7eb2e8f9f7 470
<> 144:ef7eb2e8f9f7 471 /* If error situation occurred, it is difficult to know */
<> 144:ef7eb2e8f9f7 472 /* exact cause and how to resolve. It will be up to a wrapper */
<> 144:ef7eb2e8f9f7 473 /* to determine how to handle a fault/recovery if possible. */
<> 144:ef7eb2e8f9f7 474 transfer->state = i2cStateDone;
<> 144:ef7eb2e8f9f7 475 goto done;
<> 144:ef7eb2e8f9f7 476 }
<> 144:ef7eb2e8f9f7 477
<> 144:ef7eb2e8f9f7 478 switch (transfer->state)
<> 144:ef7eb2e8f9f7 479 {
<> 144:ef7eb2e8f9f7 480 /***************************************************/
<> 144:ef7eb2e8f9f7 481 /* Send first start+address (first byte if 10 bit) */
<> 144:ef7eb2e8f9f7 482 /***************************************************/
<> 144:ef7eb2e8f9f7 483 case i2cStateStartAddrSend:
<> 144:ef7eb2e8f9f7 484 if (seq->flags & I2C_FLAG_10BIT_ADDR)
<> 144:ef7eb2e8f9f7 485 {
<> 144:ef7eb2e8f9f7 486 tmp = (((uint32_t)(seq->addr) >> 8) & 0x06) | 0xf0;
<> 144:ef7eb2e8f9f7 487
<> 144:ef7eb2e8f9f7 488 /* In 10 bit address mode, the address following the first */
<> 144:ef7eb2e8f9f7 489 /* start always indicate write. */
<> 144:ef7eb2e8f9f7 490 }
<> 144:ef7eb2e8f9f7 491 else
<> 144:ef7eb2e8f9f7 492 {
<> 144:ef7eb2e8f9f7 493 tmp = (uint32_t)(seq->addr) & 0xfe;
<> 144:ef7eb2e8f9f7 494
<> 144:ef7eb2e8f9f7 495 if (seq->flags & I2C_FLAG_READ)
<> 144:ef7eb2e8f9f7 496 {
<> 144:ef7eb2e8f9f7 497 /* Indicate read request */
<> 144:ef7eb2e8f9f7 498 tmp |= 1;
<> 144:ef7eb2e8f9f7 499 }
<> 144:ef7eb2e8f9f7 500 }
<> 144:ef7eb2e8f9f7 501
<> 144:ef7eb2e8f9f7 502 transfer->state = i2cStateAddrWFAckNack;
<> 144:ef7eb2e8f9f7 503 i2c->TXDATA = tmp; /* Data not transmitted until START sent */
<> 144:ef7eb2e8f9f7 504 i2c->CMD = I2C_CMD_START;
<> 144:ef7eb2e8f9f7 505 goto done;
<> 144:ef7eb2e8f9f7 506
<> 144:ef7eb2e8f9f7 507 /*******************************************************/
<> 144:ef7eb2e8f9f7 508 /* Wait for ACK/NACK on address (first byte if 10 bit) */
<> 144:ef7eb2e8f9f7 509 /*******************************************************/
<> 144:ef7eb2e8f9f7 510 case i2cStateAddrWFAckNack:
<> 144:ef7eb2e8f9f7 511 if (pending & I2C_IF_NACK)
<> 144:ef7eb2e8f9f7 512 {
<> 144:ef7eb2e8f9f7 513 i2c->IFC = I2C_IFC_NACK;
<> 144:ef7eb2e8f9f7 514 transfer->result = i2cTransferNack;
<> 144:ef7eb2e8f9f7 515 transfer->state = i2cStateWFStopSent;
<> 144:ef7eb2e8f9f7 516 i2c->CMD = I2C_CMD_STOP;
<> 144:ef7eb2e8f9f7 517 }
<> 144:ef7eb2e8f9f7 518 else if (pending & I2C_IF_ACK)
<> 144:ef7eb2e8f9f7 519 {
<> 144:ef7eb2e8f9f7 520 i2c->IFC = I2C_IFC_ACK;
<> 144:ef7eb2e8f9f7 521
<> 144:ef7eb2e8f9f7 522 /* If 10 bit address, send 2nd byte of address. */
<> 144:ef7eb2e8f9f7 523 if (seq->flags & I2C_FLAG_10BIT_ADDR)
<> 144:ef7eb2e8f9f7 524 {
<> 144:ef7eb2e8f9f7 525 transfer->state = i2cStateAddrWF2ndAckNack;
<> 144:ef7eb2e8f9f7 526 i2c->TXDATA = (uint32_t)(seq->addr) & 0xff;
<> 144:ef7eb2e8f9f7 527 }
<> 144:ef7eb2e8f9f7 528 else
<> 144:ef7eb2e8f9f7 529 {
<> 144:ef7eb2e8f9f7 530 /* Determine whether receiving or sending data */
<> 144:ef7eb2e8f9f7 531 if (seq->flags & I2C_FLAG_READ)
<> 144:ef7eb2e8f9f7 532 {
<> 144:ef7eb2e8f9f7 533 transfer->state = i2cStateWFData;
<> 144:ef7eb2e8f9f7 534 if(seq->buf[transfer->bufIndx].len==1)
<> 144:ef7eb2e8f9f7 535 {
<> 144:ef7eb2e8f9f7 536 i2c->CMD = I2C_CMD_NACK;
<> 144:ef7eb2e8f9f7 537 }
<> 144:ef7eb2e8f9f7 538 }
<> 144:ef7eb2e8f9f7 539 else
<> 144:ef7eb2e8f9f7 540 {
<> 144:ef7eb2e8f9f7 541 transfer->state = i2cStateDataSend;
<> 144:ef7eb2e8f9f7 542 continue;
<> 144:ef7eb2e8f9f7 543 }
<> 144:ef7eb2e8f9f7 544 }
<> 144:ef7eb2e8f9f7 545 }
<> 144:ef7eb2e8f9f7 546 goto done;
<> 144:ef7eb2e8f9f7 547
<> 144:ef7eb2e8f9f7 548 /******************************************************/
<> 144:ef7eb2e8f9f7 549 /* Wait for ACK/NACK on second byte of 10 bit address */
<> 144:ef7eb2e8f9f7 550 /******************************************************/
<> 144:ef7eb2e8f9f7 551 case i2cStateAddrWF2ndAckNack:
<> 144:ef7eb2e8f9f7 552 if (pending & I2C_IF_NACK)
<> 144:ef7eb2e8f9f7 553 {
<> 144:ef7eb2e8f9f7 554 i2c->IFC = I2C_IFC_NACK;
<> 144:ef7eb2e8f9f7 555 transfer->result = i2cTransferNack;
<> 144:ef7eb2e8f9f7 556 transfer->state = i2cStateWFStopSent;
<> 144:ef7eb2e8f9f7 557 i2c->CMD = I2C_CMD_STOP;
<> 144:ef7eb2e8f9f7 558 }
<> 144:ef7eb2e8f9f7 559 else if (pending & I2C_IF_ACK)
<> 144:ef7eb2e8f9f7 560 {
<> 144:ef7eb2e8f9f7 561 i2c->IFC = I2C_IFC_ACK;
<> 144:ef7eb2e8f9f7 562
<> 144:ef7eb2e8f9f7 563 /* If using plain read sequence with 10 bit address, switch to send */
<> 144:ef7eb2e8f9f7 564 /* repeated start. */
<> 144:ef7eb2e8f9f7 565 if (seq->flags & I2C_FLAG_READ)
<> 144:ef7eb2e8f9f7 566 {
<> 144:ef7eb2e8f9f7 567 transfer->state = i2cStateRStartAddrSend;
<> 144:ef7eb2e8f9f7 568 }
<> 144:ef7eb2e8f9f7 569 /* Otherwise expected to write 0 or more bytes */
<> 144:ef7eb2e8f9f7 570 else
<> 144:ef7eb2e8f9f7 571 {
<> 144:ef7eb2e8f9f7 572 transfer->state = i2cStateDataSend;
<> 144:ef7eb2e8f9f7 573 }
<> 144:ef7eb2e8f9f7 574 continue;
<> 144:ef7eb2e8f9f7 575 }
<> 144:ef7eb2e8f9f7 576 goto done;
<> 144:ef7eb2e8f9f7 577
<> 144:ef7eb2e8f9f7 578 /*******************************/
<> 144:ef7eb2e8f9f7 579 /* Send repeated start+address */
<> 144:ef7eb2e8f9f7 580 /*******************************/
<> 144:ef7eb2e8f9f7 581 case i2cStateRStartAddrSend:
<> 144:ef7eb2e8f9f7 582 if (seq->flags & I2C_FLAG_10BIT_ADDR)
<> 144:ef7eb2e8f9f7 583 {
<> 144:ef7eb2e8f9f7 584 tmp = ((seq->addr >> 8) & 0x06) | 0xf0;
<> 144:ef7eb2e8f9f7 585 }
<> 144:ef7eb2e8f9f7 586 else
<> 144:ef7eb2e8f9f7 587 {
<> 144:ef7eb2e8f9f7 588 tmp = seq->addr & 0xfe;
<> 144:ef7eb2e8f9f7 589 }
<> 144:ef7eb2e8f9f7 590
<> 144:ef7eb2e8f9f7 591 /* If this is a write+read combined sequence, then read is about to start */
<> 144:ef7eb2e8f9f7 592 if (seq->flags & I2C_FLAG_WRITE_READ)
<> 144:ef7eb2e8f9f7 593 {
<> 144:ef7eb2e8f9f7 594 /* Indicate read request */
<> 144:ef7eb2e8f9f7 595 tmp |= 1;
<> 144:ef7eb2e8f9f7 596 }
<> 144:ef7eb2e8f9f7 597
<> 144:ef7eb2e8f9f7 598 transfer->state = i2cStateRAddrWFAckNack;
<> 144:ef7eb2e8f9f7 599 /* We have to write START cmd first since repeated start, otherwise */
<> 144:ef7eb2e8f9f7 600 /* data would be sent first. */
<> 144:ef7eb2e8f9f7 601 i2c->CMD = I2C_CMD_START;
<> 144:ef7eb2e8f9f7 602 i2c->TXDATA = tmp;
<> 144:ef7eb2e8f9f7 603 goto done;
<> 144:ef7eb2e8f9f7 604
<> 144:ef7eb2e8f9f7 605 /**********************************************************************/
<> 144:ef7eb2e8f9f7 606 /* Wait for ACK/NACK on repeated start+address (first byte if 10 bit) */
<> 144:ef7eb2e8f9f7 607 /**********************************************************************/
<> 144:ef7eb2e8f9f7 608 case i2cStateRAddrWFAckNack:
<> 144:ef7eb2e8f9f7 609 if (pending & I2C_IF_NACK)
<> 144:ef7eb2e8f9f7 610 {
<> 144:ef7eb2e8f9f7 611 i2c->IFC = I2C_IFC_NACK;
<> 144:ef7eb2e8f9f7 612 transfer->result = i2cTransferNack;
<> 144:ef7eb2e8f9f7 613 transfer->state = i2cStateWFStopSent;
<> 144:ef7eb2e8f9f7 614 i2c->CMD = I2C_CMD_STOP;
<> 144:ef7eb2e8f9f7 615 }
<> 144:ef7eb2e8f9f7 616 else if (pending & I2C_IF_ACK)
<> 144:ef7eb2e8f9f7 617 {
<> 144:ef7eb2e8f9f7 618 i2c->IFC = I2C_IFC_ACK;
<> 144:ef7eb2e8f9f7 619
<> 144:ef7eb2e8f9f7 620 /* Determine whether receiving or sending data */
<> 144:ef7eb2e8f9f7 621 if (seq->flags & I2C_FLAG_WRITE_READ)
<> 144:ef7eb2e8f9f7 622 {
<> 144:ef7eb2e8f9f7 623 transfer->state = i2cStateWFData;
<> 144:ef7eb2e8f9f7 624 }
<> 144:ef7eb2e8f9f7 625 else
<> 144:ef7eb2e8f9f7 626 {
<> 144:ef7eb2e8f9f7 627 transfer->state = i2cStateDataSend;
<> 144:ef7eb2e8f9f7 628 continue;
<> 144:ef7eb2e8f9f7 629 }
<> 144:ef7eb2e8f9f7 630 }
<> 144:ef7eb2e8f9f7 631 goto done;
<> 144:ef7eb2e8f9f7 632
<> 144:ef7eb2e8f9f7 633 /*****************************/
<> 144:ef7eb2e8f9f7 634 /* Send a data byte to slave */
<> 144:ef7eb2e8f9f7 635 /*****************************/
<> 144:ef7eb2e8f9f7 636 case i2cStateDataSend:
<> 144:ef7eb2e8f9f7 637 /* Reached end of data buffer? */
<> 144:ef7eb2e8f9f7 638 if (transfer->offset >= seq->buf[transfer->bufIndx].len)
<> 144:ef7eb2e8f9f7 639 {
<> 144:ef7eb2e8f9f7 640 /* Move to next message part */
<> 144:ef7eb2e8f9f7 641 transfer->offset = 0;
<> 144:ef7eb2e8f9f7 642 transfer->bufIndx++;
<> 144:ef7eb2e8f9f7 643
<> 144:ef7eb2e8f9f7 644 /* Send repeated start when switching to read mode on 2nd buffer */
<> 144:ef7eb2e8f9f7 645 if (seq->flags & I2C_FLAG_WRITE_READ)
<> 144:ef7eb2e8f9f7 646 {
<> 144:ef7eb2e8f9f7 647 transfer->state = i2cStateRStartAddrSend;
<> 144:ef7eb2e8f9f7 648 continue;
<> 144:ef7eb2e8f9f7 649 }
<> 144:ef7eb2e8f9f7 650
<> 144:ef7eb2e8f9f7 651 /* Only writing from one buffer, or finished both buffers */
<> 144:ef7eb2e8f9f7 652 if ((seq->flags & I2C_FLAG_WRITE) || (transfer->bufIndx > 1))
<> 144:ef7eb2e8f9f7 653 {
<> 144:ef7eb2e8f9f7 654 transfer->state = i2cStateWFStopSent;
<> 144:ef7eb2e8f9f7 655 i2c->CMD = I2C_CMD_STOP;
<> 144:ef7eb2e8f9f7 656 goto done;
<> 144:ef7eb2e8f9f7 657 }
<> 144:ef7eb2e8f9f7 658
<> 144:ef7eb2e8f9f7 659 /* Reprocess in case next buffer is empty */
<> 144:ef7eb2e8f9f7 660 continue;
<> 144:ef7eb2e8f9f7 661 }
<> 144:ef7eb2e8f9f7 662
<> 144:ef7eb2e8f9f7 663 /* Send byte */
<> 144:ef7eb2e8f9f7 664 i2c->TXDATA = (uint32_t)(seq->buf[transfer->bufIndx].data[transfer->offset++]);
<> 144:ef7eb2e8f9f7 665 transfer->state = i2cStateDataWFAckNack;
<> 144:ef7eb2e8f9f7 666 goto done;
<> 144:ef7eb2e8f9f7 667
<> 144:ef7eb2e8f9f7 668 /*********************************************************/
<> 144:ef7eb2e8f9f7 669 /* Wait for ACK/NACK from slave after sending data to it */
<> 144:ef7eb2e8f9f7 670 /*********************************************************/
<> 144:ef7eb2e8f9f7 671 case i2cStateDataWFAckNack:
<> 144:ef7eb2e8f9f7 672 if (pending & I2C_IF_NACK)
<> 144:ef7eb2e8f9f7 673 {
<> 144:ef7eb2e8f9f7 674 i2c->IFC = I2C_IFC_NACK;
<> 144:ef7eb2e8f9f7 675 transfer->result = i2cTransferNack;
<> 144:ef7eb2e8f9f7 676 transfer->state = i2cStateWFStopSent;
<> 144:ef7eb2e8f9f7 677 i2c->CMD = I2C_CMD_STOP;
<> 144:ef7eb2e8f9f7 678 }
<> 144:ef7eb2e8f9f7 679 else if (pending & I2C_IF_ACK)
<> 144:ef7eb2e8f9f7 680 {
<> 144:ef7eb2e8f9f7 681 i2c->IFC = I2C_IFC_ACK;
<> 144:ef7eb2e8f9f7 682 transfer->state = i2cStateDataSend;
<> 144:ef7eb2e8f9f7 683 continue;
<> 144:ef7eb2e8f9f7 684 }
<> 144:ef7eb2e8f9f7 685 goto done;
<> 144:ef7eb2e8f9f7 686
<> 144:ef7eb2e8f9f7 687 /****************************/
<> 144:ef7eb2e8f9f7 688 /* Wait for data from slave */
<> 144:ef7eb2e8f9f7 689 /****************************/
<> 144:ef7eb2e8f9f7 690 case i2cStateWFData:
<> 144:ef7eb2e8f9f7 691 if (pending & I2C_IF_RXDATAV)
<> 144:ef7eb2e8f9f7 692 {
<> 144:ef7eb2e8f9f7 693 uint8_t data;
<> 144:ef7eb2e8f9f7 694 unsigned int rxLen = seq->buf[transfer->bufIndx].len;
<> 144:ef7eb2e8f9f7 695
<> 144:ef7eb2e8f9f7 696 /* Must read out data in order to not block further progress */
<> 144:ef7eb2e8f9f7 697 data = (uint8_t)(i2c->RXDATA);
<> 144:ef7eb2e8f9f7 698
<> 144:ef7eb2e8f9f7 699 /* Make sure not storing beyond end of buffer just in case */
<> 144:ef7eb2e8f9f7 700 if (transfer->offset < rxLen)
<> 144:ef7eb2e8f9f7 701 {
<> 144:ef7eb2e8f9f7 702 seq->buf[transfer->bufIndx].data[transfer->offset++] = data;
<> 144:ef7eb2e8f9f7 703 }
<> 144:ef7eb2e8f9f7 704
<> 144:ef7eb2e8f9f7 705 /* If we have read all requested data, then the sequence should end */
<> 144:ef7eb2e8f9f7 706 if (transfer->offset >= rxLen)
<> 144:ef7eb2e8f9f7 707 {
<> 144:ef7eb2e8f9f7 708 /* If there is only one byte to receive we need to transmit the
<> 144:ef7eb2e8f9f7 709 NACK now, before the stop. */
<> 144:ef7eb2e8f9f7 710 if (1 == rxLen)
<> 144:ef7eb2e8f9f7 711 {
<> 144:ef7eb2e8f9f7 712 i2c->CMD = I2C_CMD_NACK;
<> 144:ef7eb2e8f9f7 713 }
<> 144:ef7eb2e8f9f7 714
<> 144:ef7eb2e8f9f7 715 transfer->state = i2cStateWFStopSent;
<> 144:ef7eb2e8f9f7 716 i2c->CMD = I2C_CMD_STOP;
<> 144:ef7eb2e8f9f7 717 }
<> 144:ef7eb2e8f9f7 718 else
<> 144:ef7eb2e8f9f7 719 {
<> 144:ef7eb2e8f9f7 720 /* Send ACK and wait for next byte */
<> 144:ef7eb2e8f9f7 721 i2c->CMD = I2C_CMD_ACK;
<> 144:ef7eb2e8f9f7 722
<> 144:ef7eb2e8f9f7 723 if ( (1<rxLen) && (transfer->offset == (rxLen-1)) )
<> 144:ef7eb2e8f9f7 724 {
<> 144:ef7eb2e8f9f7 725 /* If there is more than one byte to receive and this is the next
<> 144:ef7eb2e8f9f7 726 to last byte we need to transmit the NACK now, before receiving
<> 144:ef7eb2e8f9f7 727 the last byte. */
<> 144:ef7eb2e8f9f7 728 i2c->CMD = I2C_CMD_NACK;
<> 144:ef7eb2e8f9f7 729 }
<> 144:ef7eb2e8f9f7 730 }
<> 144:ef7eb2e8f9f7 731 }
<> 144:ef7eb2e8f9f7 732 goto done;
<> 144:ef7eb2e8f9f7 733
<> 144:ef7eb2e8f9f7 734 /***********************************/
<> 144:ef7eb2e8f9f7 735 /* Wait for STOP to have been sent */
<> 144:ef7eb2e8f9f7 736 /***********************************/
<> 144:ef7eb2e8f9f7 737 case i2cStateWFStopSent:
<> 144:ef7eb2e8f9f7 738 if (pending & I2C_IF_MSTOP)
<> 144:ef7eb2e8f9f7 739 {
<> 144:ef7eb2e8f9f7 740 i2c->IFC = I2C_IFC_MSTOP;
<> 144:ef7eb2e8f9f7 741 transfer->state = i2cStateDone;
<> 144:ef7eb2e8f9f7 742 }
<> 144:ef7eb2e8f9f7 743 goto done;
<> 144:ef7eb2e8f9f7 744
<> 144:ef7eb2e8f9f7 745 /******************************/
<> 144:ef7eb2e8f9f7 746 /* Unexpected state, SW fault */
<> 144:ef7eb2e8f9f7 747 /******************************/
<> 144:ef7eb2e8f9f7 748 default:
<> 144:ef7eb2e8f9f7 749 transfer->result = i2cTransferSwFault;
<> 144:ef7eb2e8f9f7 750 transfer->state = i2cStateDone;
<> 144:ef7eb2e8f9f7 751 goto done;
<> 144:ef7eb2e8f9f7 752 }
<> 144:ef7eb2e8f9f7 753 }
<> 144:ef7eb2e8f9f7 754
<> 144:ef7eb2e8f9f7 755 done:
<> 144:ef7eb2e8f9f7 756
<> 144:ef7eb2e8f9f7 757 if (transfer->state == i2cStateDone)
<> 144:ef7eb2e8f9f7 758 {
<> 144:ef7eb2e8f9f7 759 /* Disable interrupt sources when done */
<> 144:ef7eb2e8f9f7 760 i2c->IEN = 0;
<> 144:ef7eb2e8f9f7 761
<> 144:ef7eb2e8f9f7 762 /* Update result unless some fault already occurred */
<> 144:ef7eb2e8f9f7 763 if (transfer->result == i2cTransferInProgress)
<> 144:ef7eb2e8f9f7 764 {
<> 144:ef7eb2e8f9f7 765 transfer->result = i2cTransferDone;
<> 144:ef7eb2e8f9f7 766 }
<> 144:ef7eb2e8f9f7 767 }
<> 144:ef7eb2e8f9f7 768 /* Until transfer is done keep returning i2cTransferInProgress */
<> 144:ef7eb2e8f9f7 769 else
<> 144:ef7eb2e8f9f7 770 {
<> 144:ef7eb2e8f9f7 771 return i2cTransferInProgress;
<> 144:ef7eb2e8f9f7 772 }
<> 144:ef7eb2e8f9f7 773
<> 144:ef7eb2e8f9f7 774 return transfer->result;
<> 144:ef7eb2e8f9f7 775 }
<> 144:ef7eb2e8f9f7 776
<> 144:ef7eb2e8f9f7 777
<> 144:ef7eb2e8f9f7 778 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 779 * @brief
<> 144:ef7eb2e8f9f7 780 * Prepare and start an I2C transfer (single master mode only).
<> 144:ef7eb2e8f9f7 781 *
<> 144:ef7eb2e8f9f7 782 * @details
<> 144:ef7eb2e8f9f7 783 * This function must be invoked in order to start an I2C transfer
<> 144:ef7eb2e8f9f7 784 * sequence. In order to actually complete the transfer, I2C_Transfer() must
<> 144:ef7eb2e8f9f7 785 * be used either in polled mode or by adding a small driver wrapper utilizing
<> 144:ef7eb2e8f9f7 786 * interrupts.
<> 144:ef7eb2e8f9f7 787 *
<> 144:ef7eb2e8f9f7 788 * @note
<> 144:ef7eb2e8f9f7 789 * Only single master mode is supported.
<> 144:ef7eb2e8f9f7 790 *
<> 144:ef7eb2e8f9f7 791 * @param[in] i2c
<> 144:ef7eb2e8f9f7 792 * Pointer to I2C peripheral register block.
<> 144:ef7eb2e8f9f7 793 *
<> 144:ef7eb2e8f9f7 794 * @param[in] seq
<> 144:ef7eb2e8f9f7 795 * Pointer to sequence structure defining the I2C transfer to take place. The
<> 144:ef7eb2e8f9f7 796 * referenced structure must exist until the transfer has fully completed.
<> 144:ef7eb2e8f9f7 797 *
<> 144:ef7eb2e8f9f7 798 * @return
<> 144:ef7eb2e8f9f7 799 * Returns status for ongoing transfer:
<> 144:ef7eb2e8f9f7 800 * @li #i2cTransferInProgress - indicates that transfer not finished.
<> 144:ef7eb2e8f9f7 801 * @li otherwise some sort of error has occurred.
<> 144:ef7eb2e8f9f7 802 ******************************************************************************/
<> 144:ef7eb2e8f9f7 803 I2C_TransferReturn_TypeDef I2C_TransferInit(I2C_TypeDef *i2c,
<> 144:ef7eb2e8f9f7 804 I2C_TransferSeq_TypeDef *seq)
<> 144:ef7eb2e8f9f7 805 {
<> 144:ef7eb2e8f9f7 806 I2C_Transfer_TypeDef *transfer;
<> 144:ef7eb2e8f9f7 807
<> 144:ef7eb2e8f9f7 808 EFM_ASSERT(I2C_REF_VALID(i2c));
<> 144:ef7eb2e8f9f7 809 EFM_ASSERT(seq);
<> 144:ef7eb2e8f9f7 810
<> 144:ef7eb2e8f9f7 811 /* Support up to 2 I2C buses */
<> 144:ef7eb2e8f9f7 812 if (i2c == I2C0)
<> 144:ef7eb2e8f9f7 813 {
<> 144:ef7eb2e8f9f7 814 transfer = i2cTransfer;
<> 144:ef7eb2e8f9f7 815 }
<> 144:ef7eb2e8f9f7 816 #if (I2C_COUNT > 1)
<> 144:ef7eb2e8f9f7 817 else if (i2c == I2C1)
<> 144:ef7eb2e8f9f7 818 {
<> 144:ef7eb2e8f9f7 819 transfer = i2cTransfer + 1;
<> 144:ef7eb2e8f9f7 820 }
<> 144:ef7eb2e8f9f7 821 #endif
<> 144:ef7eb2e8f9f7 822 else
<> 144:ef7eb2e8f9f7 823 {
<> 144:ef7eb2e8f9f7 824 return i2cTransferUsageFault;
<> 144:ef7eb2e8f9f7 825 }
<> 144:ef7eb2e8f9f7 826
<> 144:ef7eb2e8f9f7 827 /* Check if in busy state. Since this SW assumes single master, we can */
<> 144:ef7eb2e8f9f7 828 /* just issue an abort. The BUSY state is normal after a reset. */
<> 144:ef7eb2e8f9f7 829 if (i2c->STATE & I2C_STATE_BUSY)
<> 144:ef7eb2e8f9f7 830 {
<> 144:ef7eb2e8f9f7 831 i2c->CMD = I2C_CMD_ABORT;
<> 144:ef7eb2e8f9f7 832 }
<> 144:ef7eb2e8f9f7 833
<> 144:ef7eb2e8f9f7 834 /* Make sure user is not trying to read 0 bytes, it is not */
<> 144:ef7eb2e8f9f7 835 /* possible according to I2C spec, since slave will always start */
<> 144:ef7eb2e8f9f7 836 /* sending first byte ACK on address. The read operation can */
<> 144:ef7eb2e8f9f7 837 /* only be stopped by NACKing a received byte, ie minimum 1 byte. */
<> 144:ef7eb2e8f9f7 838 if (((seq->flags & I2C_FLAG_READ) && !(seq->buf[0].len)) ||
<> 144:ef7eb2e8f9f7 839 ((seq->flags & I2C_FLAG_WRITE_READ) && !(seq->buf[1].len))
<> 144:ef7eb2e8f9f7 840 )
<> 144:ef7eb2e8f9f7 841 {
<> 144:ef7eb2e8f9f7 842 return i2cTransferUsageFault;
<> 144:ef7eb2e8f9f7 843 }
<> 144:ef7eb2e8f9f7 844
<> 144:ef7eb2e8f9f7 845 /* Prepare for a transfer */
<> 144:ef7eb2e8f9f7 846 transfer->state = i2cStateStartAddrSend;
<> 144:ef7eb2e8f9f7 847 transfer->result = i2cTransferInProgress;
<> 144:ef7eb2e8f9f7 848 transfer->offset = 0;
<> 144:ef7eb2e8f9f7 849 transfer->bufIndx = 0;
<> 144:ef7eb2e8f9f7 850 transfer->seq = seq;
<> 144:ef7eb2e8f9f7 851
<> 144:ef7eb2e8f9f7 852 /* Ensure buffers are empty */
<> 144:ef7eb2e8f9f7 853 i2c->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
<> 144:ef7eb2e8f9f7 854 if (i2c->IF & I2C_IF_RXDATAV)
<> 144:ef7eb2e8f9f7 855 {
<> 144:ef7eb2e8f9f7 856 (void)i2c->RXDATA;
<> 144:ef7eb2e8f9f7 857 }
<> 144:ef7eb2e8f9f7 858
<> 144:ef7eb2e8f9f7 859 /* Clear all pending interrupts prior to starting transfer. */
<> 144:ef7eb2e8f9f7 860 i2c->IFC = _I2C_IFC_MASK;
<> 144:ef7eb2e8f9f7 861
<> 144:ef7eb2e8f9f7 862 /* Enable those interrupts we are interested in throughout transfer. */
<> 144:ef7eb2e8f9f7 863 /* Notice that the I2C interrupt must also be enabled in the NVIC, but */
<> 144:ef7eb2e8f9f7 864 /* that is left for an additional driver wrapper. */
<> 144:ef7eb2e8f9f7 865 i2c->IEN = I2C_IF_NACK | I2C_IF_ACK | I2C_IF_MSTOP |
<> 144:ef7eb2e8f9f7 866 I2C_IF_RXDATAV | I2C_IF_ERRORS;
<> 144:ef7eb2e8f9f7 867
<> 144:ef7eb2e8f9f7 868 /* Start transfer */
<> 144:ef7eb2e8f9f7 869 return I2C_Transfer(i2c);
<> 144:ef7eb2e8f9f7 870 }
<> 144:ef7eb2e8f9f7 871
<> 144:ef7eb2e8f9f7 872 /** @} (end addtogroup I2C) */
<> 144:ef7eb2e8f9f7 873 /** @} (end addtogroup EM_Library) */
<> 144:ef7eb2e8f9f7 874 #endif /* defined(I2C_COUNT) && (I2C_COUNT > 0) */