added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

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) */