mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
186:707f6e361f3e
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Anna Bridge 186:707f6e361f3e 1 /**
Anna Bridge 186:707f6e361f3e 2 * @file
Anna Bridge 186:707f6e361f3e 3 * @brief This file contains the function implementations for the I2CM
Anna Bridge 186:707f6e361f3e 4 * (Inter-Integrated Circuit Master) peripheral module.
Anna Bridge 186:707f6e361f3e 5 */
Anna Bridge 186:707f6e361f3e 6
Anna Bridge 186:707f6e361f3e 7 /* ****************************************************************************
Anna Bridge 186:707f6e361f3e 8 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
Anna Bridge 186:707f6e361f3e 9 *
Anna Bridge 186:707f6e361f3e 10 * Permission is hereby granted, free of charge, to any person obtaining a
Anna Bridge 186:707f6e361f3e 11 * copy of this software and associated documentation files (the "Software"),
Anna Bridge 186:707f6e361f3e 12 * to deal in the Software without restriction, including without limitation
Anna Bridge 186:707f6e361f3e 13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
Anna Bridge 186:707f6e361f3e 14 * and/or sell copies of the Software, and to permit persons to whom the
Anna Bridge 186:707f6e361f3e 15 * Software is furnished to do so, subject to the following conditions:
Anna Bridge 186:707f6e361f3e 16 *
Anna Bridge 186:707f6e361f3e 17 * The above copyright notice and this permission notice shall be included
Anna Bridge 186:707f6e361f3e 18 * in all copies or substantial portions of the Software.
Anna Bridge 186:707f6e361f3e 19 *
Anna Bridge 186:707f6e361f3e 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
Anna Bridge 186:707f6e361f3e 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Anna Bridge 186:707f6e361f3e 22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Anna Bridge 186:707f6e361f3e 23 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
Anna Bridge 186:707f6e361f3e 24 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
Anna Bridge 186:707f6e361f3e 25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
Anna Bridge 186:707f6e361f3e 26 * OTHER DEALINGS IN THE SOFTWARE.
Anna Bridge 186:707f6e361f3e 27 *
Anna Bridge 186:707f6e361f3e 28 * Except as contained in this notice, the name of Maxim Integrated
Anna Bridge 186:707f6e361f3e 29 * Products, Inc. shall not be used except as stated in the Maxim Integrated
Anna Bridge 186:707f6e361f3e 30 * Products, Inc. Branding Policy.
Anna Bridge 186:707f6e361f3e 31 *
Anna Bridge 186:707f6e361f3e 32 * The mere transfer of this software does not imply any licenses
Anna Bridge 186:707f6e361f3e 33 * of trade secrets, proprietary technology, copyrights, patents,
Anna Bridge 186:707f6e361f3e 34 * trademarks, maskwork rights, or any other form of intellectual
Anna Bridge 186:707f6e361f3e 35 * property whatsoever. Maxim Integrated Products, Inc. retains all
Anna Bridge 186:707f6e361f3e 36 * ownership rights.
Anna Bridge 186:707f6e361f3e 37 *
Anna Bridge 186:707f6e361f3e 38 * $Date: 2016-09-09 11:40:02 -0500 (Fri, 09 Sep 2016) $
Anna Bridge 186:707f6e361f3e 39 * $Revision: 24336 $
Anna Bridge 186:707f6e361f3e 40 *
Anna Bridge 186:707f6e361f3e 41 *************************************************************************** */
Anna Bridge 186:707f6e361f3e 42
Anna Bridge 186:707f6e361f3e 43 /* **** Includes **** */
Anna Bridge 186:707f6e361f3e 44 #include <string.h>
Anna Bridge 186:707f6e361f3e 45 #include "mxc_assert.h"
Anna Bridge 186:707f6e361f3e 46 #include "mxc_lock.h"
Anna Bridge 186:707f6e361f3e 47 #include "mxc_errors.h"
Anna Bridge 186:707f6e361f3e 48 #include "mxc_sys.h"
Anna Bridge 186:707f6e361f3e 49 #include "i2cm.h"
Anna Bridge 186:707f6e361f3e 50
Anna Bridge 186:707f6e361f3e 51
Anna Bridge 186:707f6e361f3e 52 /**
Anna Bridge 186:707f6e361f3e 53 * @ingroup i2cm
Anna Bridge 186:707f6e361f3e 54 * @{
Anna Bridge 186:707f6e361f3e 55 */
Anna Bridge 186:707f6e361f3e 56
Anna Bridge 186:707f6e361f3e 57 ///@cond
Anna Bridge 186:707f6e361f3e 58 // No Doxygen documentation for the items between here and endcond.
Anna Bridge 186:707f6e361f3e 59 /* **** Definitions **** */
Anna Bridge 186:707f6e361f3e 60 #ifndef MXC_I2CM_TX_TIMEOUT
Anna Bridge 186:707f6e361f3e 61 #define MXC_I2CM_TX_TIMEOUT 0x5000 /**< Master Transmit Timeout in number of repetitive attempts to receive an ACK/NACK or for a transmission to occur */
Anna Bridge 186:707f6e361f3e 62 #endif
Anna Bridge 186:707f6e361f3e 63
Anna Bridge 186:707f6e361f3e 64 #ifndef MXC_I2CM_RX_TIMEOUT
Anna Bridge 186:707f6e361f3e 65 #define MXC_I2CM_RX_TIMEOUT 0x5000 /**< Master Receive Timeout in number of attempts to check FIFO for received data from a slave */
Anna Bridge 186:707f6e361f3e 66 #endif
Anna Bridge 186:707f6e361f3e 67
Anna Bridge 186:707f6e361f3e 68 #define I2CM_READ_BIT 0x0001 /**< Bit location to specify a read for the I2C protocol */
Anna Bridge 186:707f6e361f3e 69 ///@cond
Anna Bridge 186:707f6e361f3e 70 #define I2CM_FIFO_DEPTH_3Q ((3 * MXC_I2CM_FIFO_DEPTH) / 4)
Anna Bridge 186:707f6e361f3e 71 #define I2CM_FIFO_DEPTH_2Q (MXC_I2CM_FIFO_DEPTH / 2)
Anna Bridge 186:707f6e361f3e 72
Anna Bridge 186:707f6e361f3e 73 #define FIFO_FROM_I2CM(x) (mxc_i2cm_fifo_regs_t *)((uint32_t)x + (MXC_BASE_I2CM0_FIFO - MXC_BASE_I2CM0))
Anna Bridge 186:707f6e361f3e 74
Anna Bridge 186:707f6e361f3e 75 //
Anna Bridge 186:707f6e361f3e 76 /* **** Globals **** */
Anna Bridge 186:707f6e361f3e 77
Anna Bridge 186:707f6e361f3e 78 /* Clock divider lookup table */
Anna Bridge 186:707f6e361f3e 79 static const uint32_t clk_div_table[3][8] = {
Anna Bridge 186:707f6e361f3e 80 /* I2CM_SPEED_100KHZ */
Anna Bridge 186:707f6e361f3e 81 {
Anna Bridge 186:707f6e361f3e 82 // 12000000
Anna Bridge 186:707f6e361f3e 83 ((6 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
Anna Bridge 186:707f6e361f3e 84 (17 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
Anna Bridge 186:707f6e361f3e 85 (72 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
Anna Bridge 186:707f6e361f3e 86 // 24000000
Anna Bridge 186:707f6e361f3e 87 ((12 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
Anna Bridge 186:707f6e361f3e 88 (38 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
Anna Bridge 186:707f6e361f3e 89 (144 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
Anna Bridge 186:707f6e361f3e 90 // 36000000 NOT SUPPORTED
Anna Bridge 186:707f6e361f3e 91 0,
Anna Bridge 186:707f6e361f3e 92 // 48000000
Anna Bridge 186:707f6e361f3e 93 ((24 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
Anna Bridge 186:707f6e361f3e 94 (80 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
Anna Bridge 186:707f6e361f3e 95 (288 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
Anna Bridge 186:707f6e361f3e 96 // 60000000 NOT SUPPORTED
Anna Bridge 186:707f6e361f3e 97 0,
Anna Bridge 186:707f6e361f3e 98 // 72000000 NOT SUPPORTED
Anna Bridge 186:707f6e361f3e 99 0,
Anna Bridge 186:707f6e361f3e 100 // 84000000 NOT SUPPORTED
Anna Bridge 186:707f6e361f3e 101 0,
Anna Bridge 186:707f6e361f3e 102 // 96000000
Anna Bridge 186:707f6e361f3e 103 ((48 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
Anna Bridge 186:707f6e361f3e 104 (164 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
Anna Bridge 186:707f6e361f3e 105 (576 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
Anna Bridge 186:707f6e361f3e 106 },
Anna Bridge 186:707f6e361f3e 107 /* I2CM_SPEED_400KHZ */
Anna Bridge 186:707f6e361f3e 108 {
Anna Bridge 186:707f6e361f3e 109 // 12000000
Anna Bridge 186:707f6e361f3e 110 ((2 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
Anna Bridge 186:707f6e361f3e 111 (1 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
Anna Bridge 186:707f6e361f3e 112 (18 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
Anna Bridge 186:707f6e361f3e 113 // 24000000
Anna Bridge 186:707f6e361f3e 114 ((3 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
Anna Bridge 186:707f6e361f3e 115 (5 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
Anna Bridge 186:707f6e361f3e 116 (36 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
Anna Bridge 186:707f6e361f3e 117 // 36000000 NOT SUPPORTED
Anna Bridge 186:707f6e361f3e 118 0,
Anna Bridge 186:707f6e361f3e 119 // 48000000
Anna Bridge 186:707f6e361f3e 120 ((6 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
Anna Bridge 186:707f6e361f3e 121 (15 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
Anna Bridge 186:707f6e361f3e 122 (72 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
Anna Bridge 186:707f6e361f3e 123 // 60000000 NOT SUPPORTED
Anna Bridge 186:707f6e361f3e 124 0,
Anna Bridge 186:707f6e361f3e 125 // 72000000 NOT SUPPORTED
Anna Bridge 186:707f6e361f3e 126 0,
Anna Bridge 186:707f6e361f3e 127 // 84000000 NOT SUPPORTED
Anna Bridge 186:707f6e361f3e 128 0,
Anna Bridge 186:707f6e361f3e 129 // 96000000
Anna Bridge 186:707f6e361f3e 130 ((12 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
Anna Bridge 186:707f6e361f3e 131 (33 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
Anna Bridge 186:707f6e361f3e 132 (144 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
Anna Bridge 186:707f6e361f3e 133 },
Anna Bridge 186:707f6e361f3e 134 };
Anna Bridge 186:707f6e361f3e 135
Anna Bridge 186:707f6e361f3e 136 // Saves the state of the non-blocking requests
Anna Bridge 186:707f6e361f3e 137 typedef enum {
Anna Bridge 186:707f6e361f3e 138 I2CM_STATE_READING = 0,
Anna Bridge 186:707f6e361f3e 139 I2CM_STATE_WRITING = 1
Anna Bridge 186:707f6e361f3e 140 } i2cm_state_t;
Anna Bridge 186:707f6e361f3e 141
Anna Bridge 186:707f6e361f3e 142 typedef struct {
Anna Bridge 186:707f6e361f3e 143 i2cm_req_t *req;
Anna Bridge 186:707f6e361f3e 144 i2cm_state_t state;
Anna Bridge 186:707f6e361f3e 145 } i2cm_req_state_t;
Anna Bridge 186:707f6e361f3e 146 static i2cm_req_state_t states[MXC_CFG_I2CM_INSTANCES];
Anna Bridge 186:707f6e361f3e 147
Anna Bridge 186:707f6e361f3e 148 /* **** Local Function Prototypes **** */
Anna Bridge 186:707f6e361f3e 149
Anna Bridge 186:707f6e361f3e 150 static void I2CM_FreeCallback(int i2cm_num, int error);
Anna Bridge 186:707f6e361f3e 151 static int I2CM_CmdHandler(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, i2cm_req_t *req);
Anna Bridge 186:707f6e361f3e 152 static int I2CM_ReadHandler(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req, int i2cm_num);
Anna Bridge 186:707f6e361f3e 153 static int I2CM_WriteHandler(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req, int i2cm_num);
Anna Bridge 186:707f6e361f3e 154 ///@endcond
Anna Bridge 186:707f6e361f3e 155 //
Anna Bridge 186:707f6e361f3e 156 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 157 int I2CM_Init(mxc_i2cm_regs_t *i2cm, const sys_cfg_i2cm_t *sys_cfg, i2cm_speed_t speed)
Anna Bridge 186:707f6e361f3e 158 {
Anna Bridge 186:707f6e361f3e 159 int err, clki;
Anna Bridge 186:707f6e361f3e 160
Anna Bridge 186:707f6e361f3e 161 // Check the base pointer
Anna Bridge 186:707f6e361f3e 162 MXC_ASSERT(MXC_I2CM_GET_IDX(i2cm) >= 0);
Anna Bridge 186:707f6e361f3e 163
Anna Bridge 186:707f6e361f3e 164 // Set system level configurations
Anna Bridge 186:707f6e361f3e 165 if ((err = SYS_I2CM_Init(i2cm, sys_cfg)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 166 return err;
Anna Bridge 186:707f6e361f3e 167 }
Anna Bridge 186:707f6e361f3e 168
Anna Bridge 186:707f6e361f3e 169 // Compute clock array index
Anna Bridge 186:707f6e361f3e 170 clki = ((SYS_I2CM_GetFreq(i2cm) / 12000000) - 1);
Anna Bridge 186:707f6e361f3e 171
Anna Bridge 186:707f6e361f3e 172 // Get clock divider settings from lookup table
Anna Bridge 186:707f6e361f3e 173 if ((speed == I2CM_SPEED_100KHZ) && (clk_div_table[I2CM_SPEED_100KHZ][clki] > 0)) {
Anna Bridge 186:707f6e361f3e 174 i2cm->fs_clk_div = clk_div_table[I2CM_SPEED_100KHZ][clki];
Anna Bridge 186:707f6e361f3e 175
Anna Bridge 186:707f6e361f3e 176 } else if ((speed == I2CM_SPEED_400KHZ) && (clk_div_table[I2CM_SPEED_400KHZ][clki] > 0)) {
Anna Bridge 186:707f6e361f3e 177 i2cm->fs_clk_div = clk_div_table[I2CM_SPEED_400KHZ][clki];
Anna Bridge 186:707f6e361f3e 178
Anna Bridge 186:707f6e361f3e 179 } else {
Anna Bridge 186:707f6e361f3e 180 // Requested speed is not achievable with the current clock setup
Anna Bridge 186:707f6e361f3e 181 return E_NOT_SUPPORTED;
Anna Bridge 186:707f6e361f3e 182 }
Anna Bridge 186:707f6e361f3e 183
Anna Bridge 186:707f6e361f3e 184 // Reset module
Anna Bridge 186:707f6e361f3e 185 i2cm->ctrl = MXC_F_I2CM_CTRL_MSTR_RESET_EN;
Anna Bridge 186:707f6e361f3e 186 i2cm->ctrl = 0;
Anna Bridge 186:707f6e361f3e 187
Anna Bridge 186:707f6e361f3e 188 // Set timeout to 255 ms and turn on the auto-stop option
Anna Bridge 186:707f6e361f3e 189 i2cm->timeout = (MXC_F_I2CM_TIMEOUT_TX_TIMEOUT | MXC_F_I2CM_TIMEOUT_AUTO_STOP_EN);
Anna Bridge 186:707f6e361f3e 190
Anna Bridge 186:707f6e361f3e 191 // Enable tx_fifo and rx_fifo
Anna Bridge 186:707f6e361f3e 192 i2cm->ctrl |= (MXC_F_I2CM_CTRL_TX_FIFO_EN | MXC_F_I2CM_CTRL_RX_FIFO_EN);
Anna Bridge 186:707f6e361f3e 193
Anna Bridge 186:707f6e361f3e 194 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 195 }
Anna Bridge 186:707f6e361f3e 196
Anna Bridge 186:707f6e361f3e 197 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 198 int I2CM_Shutdown(mxc_i2cm_regs_t *i2cm)
Anna Bridge 186:707f6e361f3e 199 {
Anna Bridge 186:707f6e361f3e 200 int i2cm_num, err;
Anna Bridge 186:707f6e361f3e 201
Anna Bridge 186:707f6e361f3e 202 // Check the base pointer
Anna Bridge 186:707f6e361f3e 203 i2cm_num = MXC_I2CM_GET_IDX(i2cm);
Anna Bridge 186:707f6e361f3e 204 MXC_ASSERT(i2cm_num >= 0);
Anna Bridge 186:707f6e361f3e 205
Anna Bridge 186:707f6e361f3e 206 // Disable and clear interrupts
Anna Bridge 186:707f6e361f3e 207 i2cm->inten = 0;
Anna Bridge 186:707f6e361f3e 208 i2cm->intfl = i2cm->intfl;
Anna Bridge 186:707f6e361f3e 209
Anna Bridge 186:707f6e361f3e 210 // Call all of the pending callbacks for this I2CM
Anna Bridge 186:707f6e361f3e 211 if(states[i2cm_num].req != NULL) {
Anna Bridge 186:707f6e361f3e 212 I2CM_Recover(i2cm);
Anna Bridge 186:707f6e361f3e 213 I2CM_FreeCallback(i2cm_num, E_SHUTDOWN);
Anna Bridge 186:707f6e361f3e 214 }
Anna Bridge 186:707f6e361f3e 215
Anna Bridge 186:707f6e361f3e 216 // Clears system level configurations
Anna Bridge 186:707f6e361f3e 217 if ((err = SYS_I2CM_Shutdown(i2cm)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 218 return err;
Anna Bridge 186:707f6e361f3e 219 }
Anna Bridge 186:707f6e361f3e 220
Anna Bridge 186:707f6e361f3e 221 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 222 }
Anna Bridge 186:707f6e361f3e 223
Anna Bridge 186:707f6e361f3e 224
Anna Bridge 186:707f6e361f3e 225 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 226 int I2CM_Read(mxc_i2cm_regs_t *i2cm, uint8_t addr, const uint8_t *cmd_data,
Anna Bridge 186:707f6e361f3e 227 uint32_t cmd_len, uint8_t* data, uint32_t len, uint8_t stop)
Anna Bridge 186:707f6e361f3e 228 {
Anna Bridge 186:707f6e361f3e 229 int error = E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 230 int retval = E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 231 mxc_i2cm_fifo_regs_t *fifo;
Anna Bridge 186:707f6e361f3e 232
Anna Bridge 186:707f6e361f3e 233 if(data == NULL) {
Anna Bridge 186:707f6e361f3e 234 return E_NULL_PTR;
Anna Bridge 186:707f6e361f3e 235 }
Anna Bridge 186:707f6e361f3e 236
Anna Bridge 186:707f6e361f3e 237 // Make sure the I2CM has been initialized
Anna Bridge 186:707f6e361f3e 238 if(i2cm->ctrl == 0) {
Anna Bridge 186:707f6e361f3e 239 return E_UNINITIALIZED;
Anna Bridge 186:707f6e361f3e 240 }
Anna Bridge 186:707f6e361f3e 241
Anna Bridge 186:707f6e361f3e 242 if(!(len > 0)) {
Anna Bridge 186:707f6e361f3e 243 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 244 }
Anna Bridge 186:707f6e361f3e 245
Anna Bridge 186:707f6e361f3e 246 // Get the FIFO pointer for this I2CM
Anna Bridge 186:707f6e361f3e 247 fifo = FIFO_FROM_I2CM(i2cm);
Anna Bridge 186:707f6e361f3e 248
Anna Bridge 186:707f6e361f3e 249 // Disable and clear the interrupts
Anna Bridge 186:707f6e361f3e 250 i2cm->inten = 0;
Anna Bridge 186:707f6e361f3e 251 i2cm->intfl = i2cm->intfl;
Anna Bridge 186:707f6e361f3e 252
Anna Bridge 186:707f6e361f3e 253 // Transmit the command if there is command data and length
Anna Bridge 186:707f6e361f3e 254 if((cmd_data != NULL) && (cmd_len > 0)) {
Anna Bridge 186:707f6e361f3e 255 retval = I2CM_Tx(i2cm, fifo, addr, cmd_data, cmd_len, 0);
Anna Bridge 186:707f6e361f3e 256 }
Anna Bridge 186:707f6e361f3e 257
Anna Bridge 186:707f6e361f3e 258 // Read data from the slave if we don't have any errors
Anna Bridge 186:707f6e361f3e 259 if(retval == E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 260 retval = I2CM_Rx(i2cm, fifo, addr, data, len, stop);
Anna Bridge 186:707f6e361f3e 261 }
Anna Bridge 186:707f6e361f3e 262
Anna Bridge 186:707f6e361f3e 263 // Wait for the transaction to complete
Anna Bridge 186:707f6e361f3e 264 if (stop) {
Anna Bridge 186:707f6e361f3e 265 if((error = I2CM_TxInProgress(i2cm)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 266 retval = error;
Anna Bridge 186:707f6e361f3e 267 }
Anna Bridge 186:707f6e361f3e 268 }
Anna Bridge 186:707f6e361f3e 269
Anna Bridge 186:707f6e361f3e 270 if(retval != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 271 return retval;
Anna Bridge 186:707f6e361f3e 272 }
Anna Bridge 186:707f6e361f3e 273
Anna Bridge 186:707f6e361f3e 274 return len;
Anna Bridge 186:707f6e361f3e 275 }
Anna Bridge 186:707f6e361f3e 276
Anna Bridge 186:707f6e361f3e 277 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 278 int I2CM_Write(mxc_i2cm_regs_t *i2cm, uint8_t addr, const uint8_t *cmd_data,
Anna Bridge 186:707f6e361f3e 279 uint32_t cmd_len, uint8_t* data, uint32_t len)
Anna Bridge 186:707f6e361f3e 280 {
Anna Bridge 186:707f6e361f3e 281 int error = E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 282 int retval = E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 283 mxc_i2cm_fifo_regs_t *fifo;
Anna Bridge 186:707f6e361f3e 284
Anna Bridge 186:707f6e361f3e 285 if(data == NULL) {
Anna Bridge 186:707f6e361f3e 286 return E_NULL_PTR;
Anna Bridge 186:707f6e361f3e 287 }
Anna Bridge 186:707f6e361f3e 288
Anna Bridge 186:707f6e361f3e 289 // Make sure the I2CM has been initialized
Anna Bridge 186:707f6e361f3e 290 if(i2cm->ctrl == 0) {
Anna Bridge 186:707f6e361f3e 291 return E_UNINITIALIZED;
Anna Bridge 186:707f6e361f3e 292 }
Anna Bridge 186:707f6e361f3e 293
Anna Bridge 186:707f6e361f3e 294 if(!(len > 0)) {
Anna Bridge 186:707f6e361f3e 295 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 296 }
Anna Bridge 186:707f6e361f3e 297
Anna Bridge 186:707f6e361f3e 298 // Get the FIFO pointer for this I2CM
Anna Bridge 186:707f6e361f3e 299 fifo = FIFO_FROM_I2CM(i2cm);
Anna Bridge 186:707f6e361f3e 300
Anna Bridge 186:707f6e361f3e 301 // Disable and clear the interrupts
Anna Bridge 186:707f6e361f3e 302 i2cm->inten = 0;
Anna Bridge 186:707f6e361f3e 303 i2cm->intfl = i2cm->intfl;
Anna Bridge 186:707f6e361f3e 304
Anna Bridge 186:707f6e361f3e 305 // Transmit the command if there is command data and length, don't send stop bit
Anna Bridge 186:707f6e361f3e 306 if((cmd_data != NULL) && (cmd_len > 0)) {
Anna Bridge 186:707f6e361f3e 307 retval = I2CM_Tx(i2cm, fifo, addr, cmd_data, cmd_len, 0);
Anna Bridge 186:707f6e361f3e 308 }
Anna Bridge 186:707f6e361f3e 309
Anna Bridge 186:707f6e361f3e 310 // Write data to the slave, send the stop bit
Anna Bridge 186:707f6e361f3e 311 if(retval == E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 312 retval = I2CM_Tx(i2cm, fifo, addr, data, len, 1);
Anna Bridge 186:707f6e361f3e 313 }
Anna Bridge 186:707f6e361f3e 314
Anna Bridge 186:707f6e361f3e 315 // Wait for the transaction to complete
Anna Bridge 186:707f6e361f3e 316 if((error = I2CM_TxInProgress(i2cm)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 317 retval = error;
Anna Bridge 186:707f6e361f3e 318 }
Anna Bridge 186:707f6e361f3e 319
Anna Bridge 186:707f6e361f3e 320 if(retval != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 321 return retval;
Anna Bridge 186:707f6e361f3e 322 }
Anna Bridge 186:707f6e361f3e 323
Anna Bridge 186:707f6e361f3e 324 return len;
Anna Bridge 186:707f6e361f3e 325 }
Anna Bridge 186:707f6e361f3e 326
Anna Bridge 186:707f6e361f3e 327 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 328 int I2CM_ReadAsync(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req)
Anna Bridge 186:707f6e361f3e 329 {
Anna Bridge 186:707f6e361f3e 330 int i2cm_num, error;
Anna Bridge 186:707f6e361f3e 331
Anna Bridge 186:707f6e361f3e 332 if(req->data == NULL) {
Anna Bridge 186:707f6e361f3e 333 return E_NULL_PTR;
Anna Bridge 186:707f6e361f3e 334 }
Anna Bridge 186:707f6e361f3e 335
Anna Bridge 186:707f6e361f3e 336 // Make sure the I2CM has been initialized
Anna Bridge 186:707f6e361f3e 337 if(i2cm->ctrl == 0) {
Anna Bridge 186:707f6e361f3e 338 return E_UNINITIALIZED;
Anna Bridge 186:707f6e361f3e 339 }
Anna Bridge 186:707f6e361f3e 340
Anna Bridge 186:707f6e361f3e 341 if(!(req->data_len > 0)) {
Anna Bridge 186:707f6e361f3e 342 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 343 }
Anna Bridge 186:707f6e361f3e 344
Anna Bridge 186:707f6e361f3e 345 i2cm_num = MXC_I2CM_GET_IDX(i2cm);
Anna Bridge 186:707f6e361f3e 346
Anna Bridge 186:707f6e361f3e 347 // Attempt to register this request
Anna Bridge 186:707f6e361f3e 348 if(mxc_get_lock((uint32_t*)&states[i2cm_num].req, (uint32_t)req) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 349 return E_BUSY;
Anna Bridge 186:707f6e361f3e 350 }
Anna Bridge 186:707f6e361f3e 351
Anna Bridge 186:707f6e361f3e 352 states[i2cm_num].state = I2CM_STATE_READING;
Anna Bridge 186:707f6e361f3e 353
Anna Bridge 186:707f6e361f3e 354 // Clear the number of bytes counter
Anna Bridge 186:707f6e361f3e 355 req->cmd_num = 0;
Anna Bridge 186:707f6e361f3e 356 req->data_num = 0;
Anna Bridge 186:707f6e361f3e 357
Anna Bridge 186:707f6e361f3e 358 // Disable and clear the interrupts
Anna Bridge 186:707f6e361f3e 359 i2cm->inten = 0;
Anna Bridge 186:707f6e361f3e 360 i2cm->intfl = i2cm->intfl;
Anna Bridge 186:707f6e361f3e 361
Anna Bridge 186:707f6e361f3e 362 // Start the read
Anna Bridge 186:707f6e361f3e 363 if((error = I2CM_ReadHandler(i2cm, req, i2cm_num)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 364 I2CM_Recover(i2cm);
Anna Bridge 186:707f6e361f3e 365 I2CM_FreeCallback(i2cm_num, error);
Anna Bridge 186:707f6e361f3e 366 return error;
Anna Bridge 186:707f6e361f3e 367 }
Anna Bridge 186:707f6e361f3e 368
Anna Bridge 186:707f6e361f3e 369 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 370 }
Anna Bridge 186:707f6e361f3e 371
Anna Bridge 186:707f6e361f3e 372 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 373 int I2CM_WriteAsync(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req)
Anna Bridge 186:707f6e361f3e 374 {
Anna Bridge 186:707f6e361f3e 375 int i2cm_num, error;
Anna Bridge 186:707f6e361f3e 376
Anna Bridge 186:707f6e361f3e 377 if(req->data == NULL) {
Anna Bridge 186:707f6e361f3e 378 return E_NULL_PTR;
Anna Bridge 186:707f6e361f3e 379 }
Anna Bridge 186:707f6e361f3e 380
Anna Bridge 186:707f6e361f3e 381 // Make sure the I2CM has been initialized
Anna Bridge 186:707f6e361f3e 382 if(i2cm->ctrl == 0) {
Anna Bridge 186:707f6e361f3e 383 return E_UNINITIALIZED;
Anna Bridge 186:707f6e361f3e 384 }
Anna Bridge 186:707f6e361f3e 385
Anna Bridge 186:707f6e361f3e 386 if(!(req->data_len > 0)) {
Anna Bridge 186:707f6e361f3e 387 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 388 }
Anna Bridge 186:707f6e361f3e 389
Anna Bridge 186:707f6e361f3e 390 i2cm_num = MXC_I2CM_GET_IDX(i2cm);
Anna Bridge 186:707f6e361f3e 391
Anna Bridge 186:707f6e361f3e 392 // Attempt to register this request
Anna Bridge 186:707f6e361f3e 393 if(mxc_get_lock((uint32_t*)&states[i2cm_num].req, (uint32_t)req) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 394 return E_BUSY;
Anna Bridge 186:707f6e361f3e 395 }
Anna Bridge 186:707f6e361f3e 396
Anna Bridge 186:707f6e361f3e 397 states[i2cm_num].state = I2CM_STATE_WRITING;
Anna Bridge 186:707f6e361f3e 398
Anna Bridge 186:707f6e361f3e 399 // Clear the number of bytes counter
Anna Bridge 186:707f6e361f3e 400 req->cmd_num = 0;
Anna Bridge 186:707f6e361f3e 401 req->data_num = 0;
Anna Bridge 186:707f6e361f3e 402
Anna Bridge 186:707f6e361f3e 403 // Disable and clear the interrupts
Anna Bridge 186:707f6e361f3e 404 i2cm->inten = 0;
Anna Bridge 186:707f6e361f3e 405 i2cm->intfl = i2cm->intfl;
Anna Bridge 186:707f6e361f3e 406
Anna Bridge 186:707f6e361f3e 407 // Start the Write
Anna Bridge 186:707f6e361f3e 408 if((error = I2CM_WriteHandler(i2cm, req, i2cm_num)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 409 I2CM_Recover(i2cm);
Anna Bridge 186:707f6e361f3e 410 I2CM_FreeCallback(i2cm_num, error);
Anna Bridge 186:707f6e361f3e 411 return error;
Anna Bridge 186:707f6e361f3e 412 }
Anna Bridge 186:707f6e361f3e 413
Anna Bridge 186:707f6e361f3e 414 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 415 }
Anna Bridge 186:707f6e361f3e 416
Anna Bridge 186:707f6e361f3e 417 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 418 int I2CM_AbortAsync(i2cm_req_t *req)
Anna Bridge 186:707f6e361f3e 419 {
Anna Bridge 186:707f6e361f3e 420 int i2cm_num;
Anna Bridge 186:707f6e361f3e 421 mxc_i2cm_regs_t *i2cm;
Anna Bridge 186:707f6e361f3e 422
Anna Bridge 186:707f6e361f3e 423 // Find the request, set to NULL
Anna Bridge 186:707f6e361f3e 424 for(i2cm_num = 0; i2cm_num < MXC_CFG_I2CM_INSTANCES; i2cm_num++)
Anna Bridge 186:707f6e361f3e 425 {
Anna Bridge 186:707f6e361f3e 426 if(req == states[i2cm_num].req) {
Anna Bridge 186:707f6e361f3e 427
Anna Bridge 186:707f6e361f3e 428 i2cm = MXC_I2CM_GET_I2CM(i2cm_num);
Anna Bridge 186:707f6e361f3e 429 I2CM_Recover(i2cm);
Anna Bridge 186:707f6e361f3e 430 I2CM_FreeCallback(i2cm_num, E_ABORT);
Anna Bridge 186:707f6e361f3e 431
Anna Bridge 186:707f6e361f3e 432 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 433 }
Anna Bridge 186:707f6e361f3e 434 }
Anna Bridge 186:707f6e361f3e 435
Anna Bridge 186:707f6e361f3e 436 return E_BAD_PARAM;
Anna Bridge 186:707f6e361f3e 437 }
Anna Bridge 186:707f6e361f3e 438
Anna Bridge 186:707f6e361f3e 439 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 440 void I2CM_Handler(mxc_i2cm_regs_t *i2cm)
Anna Bridge 186:707f6e361f3e 441 {
Anna Bridge 186:707f6e361f3e 442 uint32_t intfl;
Anna Bridge 186:707f6e361f3e 443 int i2cm_num, error;
Anna Bridge 186:707f6e361f3e 444
Anna Bridge 186:707f6e361f3e 445 // Save and clear the interrupts
Anna Bridge 186:707f6e361f3e 446 intfl = i2cm->intfl;
Anna Bridge 186:707f6e361f3e 447 i2cm->intfl = intfl;
Anna Bridge 186:707f6e361f3e 448
Anna Bridge 186:707f6e361f3e 449 // Mask the disabled interrupts
Anna Bridge 186:707f6e361f3e 450 intfl &= i2cm->inten;
Anna Bridge 186:707f6e361f3e 451
Anna Bridge 186:707f6e361f3e 452 i2cm_num = MXC_I2CM_GET_IDX(i2cm);
Anna Bridge 186:707f6e361f3e 453
Anna Bridge 186:707f6e361f3e 454 // Check for errors
Anna Bridge 186:707f6e361f3e 455 if ((intfl & MXC_F_I2CM_INTFL_TX_NACKED) || (intfl & MXC_F_I2CM_INTFL_TX_LOST_ARBITR)) {
Anna Bridge 186:707f6e361f3e 456 I2CM_Recover(i2cm);
Anna Bridge 186:707f6e361f3e 457 I2CM_FreeCallback(i2cm_num, E_COMM_ERR);
Anna Bridge 186:707f6e361f3e 458 return;
Anna Bridge 186:707f6e361f3e 459 }
Anna Bridge 186:707f6e361f3e 460
Anna Bridge 186:707f6e361f3e 461 if(intfl & MXC_F_I2CM_INTFL_TX_TIMEOUT) {
Anna Bridge 186:707f6e361f3e 462 I2CM_Recover(i2cm);
Anna Bridge 186:707f6e361f3e 463 I2CM_FreeCallback(i2cm_num, E_TIME_OUT);
Anna Bridge 186:707f6e361f3e 464 return;
Anna Bridge 186:707f6e361f3e 465 }
Anna Bridge 186:707f6e361f3e 466
Anna Bridge 186:707f6e361f3e 467 // Read or write
Anna Bridge 186:707f6e361f3e 468 if(states[i2cm_num].state == I2CM_STATE_READING) {
Anna Bridge 186:707f6e361f3e 469 if((error = I2CM_ReadHandler(i2cm, states[i2cm_num].req, i2cm_num)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 470 I2CM_Recover(i2cm);
Anna Bridge 186:707f6e361f3e 471 I2CM_FreeCallback(i2cm_num, error);
Anna Bridge 186:707f6e361f3e 472 return;
Anna Bridge 186:707f6e361f3e 473 }
Anna Bridge 186:707f6e361f3e 474
Anna Bridge 186:707f6e361f3e 475 } else if(states[i2cm_num].state == I2CM_STATE_WRITING) {
Anna Bridge 186:707f6e361f3e 476 if((error = I2CM_WriteHandler(i2cm, states[i2cm_num].req, i2cm_num)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 477 I2CM_Recover(i2cm);
Anna Bridge 186:707f6e361f3e 478 I2CM_FreeCallback(i2cm_num, error);
Anna Bridge 186:707f6e361f3e 479 return;
Anna Bridge 186:707f6e361f3e 480 }
Anna Bridge 186:707f6e361f3e 481 }
Anna Bridge 186:707f6e361f3e 482
Anna Bridge 186:707f6e361f3e 483 // Done with the transaction
Anna Bridge 186:707f6e361f3e 484 if(intfl & MXC_F_I2CM_INTFL_TX_DONE) {
Anna Bridge 186:707f6e361f3e 485 I2CM_Recover(i2cm);
Anna Bridge 186:707f6e361f3e 486 I2CM_FreeCallback(i2cm_num, E_NO_ERROR);
Anna Bridge 186:707f6e361f3e 487 }
Anna Bridge 186:707f6e361f3e 488
Anna Bridge 186:707f6e361f3e 489 }
Anna Bridge 186:707f6e361f3e 490
Anna Bridge 186:707f6e361f3e 491 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 492 int I2CM_Busy(mxc_i2cm_regs_t *i2cm)
Anna Bridge 186:707f6e361f3e 493 {
Anna Bridge 186:707f6e361f3e 494 // Check to see if there are any ongoing transactions
Anna Bridge 186:707f6e361f3e 495 if((states[MXC_I2CM_GET_IDX(i2cm)].req == NULL) &&
Anna Bridge 186:707f6e361f3e 496 !(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
Anna Bridge 186:707f6e361f3e 497
Anna Bridge 186:707f6e361f3e 498 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 499 }
Anna Bridge 186:707f6e361f3e 500
Anna Bridge 186:707f6e361f3e 501 return E_BUSY;
Anna Bridge 186:707f6e361f3e 502 }
Anna Bridge 186:707f6e361f3e 503
Anna Bridge 186:707f6e361f3e 504 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 505 int I2CM_PrepForSleep(mxc_i2cm_regs_t *i2cm)
Anna Bridge 186:707f6e361f3e 506 {
Anna Bridge 186:707f6e361f3e 507 if(I2CM_Busy(i2cm) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 508 return E_BUSY;
Anna Bridge 186:707f6e361f3e 509 }
Anna Bridge 186:707f6e361f3e 510
Anna Bridge 186:707f6e361f3e 511 // Disable interrupts
Anna Bridge 186:707f6e361f3e 512 i2cm->inten = 0;
Anna Bridge 186:707f6e361f3e 513 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 514 }
Anna Bridge 186:707f6e361f3e 515
Anna Bridge 186:707f6e361f3e 516 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 517 int I2CM_BusCheck(mxc_i2cm_regs_t *i2cm)
Anna Bridge 186:707f6e361f3e 518 {
Anna Bridge 186:707f6e361f3e 519 // If SCL is low, we don't have the bus
Anna Bridge 186:707f6e361f3e 520 if(!(i2cm->bb & MXC_F_I2CM_BB_BB_SCL_IN_VAL)) {
Anna Bridge 186:707f6e361f3e 521 return E_BUSY;
Anna Bridge 186:707f6e361f3e 522 }
Anna Bridge 186:707f6e361f3e 523
Anna Bridge 186:707f6e361f3e 524 // If SDA is low, we don't have the bus
Anna Bridge 186:707f6e361f3e 525 if(!(i2cm->bb & MXC_F_I2CM_BB_BB_SDA_IN_VAL)) {
Anna Bridge 186:707f6e361f3e 526 return E_BUSY;
Anna Bridge 186:707f6e361f3e 527 }
Anna Bridge 186:707f6e361f3e 528
Anna Bridge 186:707f6e361f3e 529 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 530 }
Anna Bridge 186:707f6e361f3e 531
Anna Bridge 186:707f6e361f3e 532 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 533 static void I2CM_FreeCallback(int i2cm_num, int error)
Anna Bridge 186:707f6e361f3e 534 {
Anna Bridge 186:707f6e361f3e 535 // Save the request
Anna Bridge 186:707f6e361f3e 536 i2cm_req_t *temp_req = states[i2cm_num].req;
Anna Bridge 186:707f6e361f3e 537
Anna Bridge 186:707f6e361f3e 538 // Unlock this UART to write
Anna Bridge 186:707f6e361f3e 539 mxc_free_lock((uint32_t*)&states[i2cm_num].req);
Anna Bridge 186:707f6e361f3e 540
Anna Bridge 186:707f6e361f3e 541 // Callback if not NULL
Anna Bridge 186:707f6e361f3e 542 if(temp_req->callback != NULL) {
Anna Bridge 186:707f6e361f3e 543 temp_req->callback(temp_req, error);
Anna Bridge 186:707f6e361f3e 544 }
Anna Bridge 186:707f6e361f3e 545 }
Anna Bridge 186:707f6e361f3e 546
Anna Bridge 186:707f6e361f3e 547 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 548 void I2CM_Recover(mxc_i2cm_regs_t *i2cm)
Anna Bridge 186:707f6e361f3e 549 {
Anna Bridge 186:707f6e361f3e 550 // Disable and clear interrupts
Anna Bridge 186:707f6e361f3e 551 i2cm->inten = 0;
Anna Bridge 186:707f6e361f3e 552 i2cm->intfl = i2cm->intfl;
Anna Bridge 186:707f6e361f3e 553 i2cm->ctrl = MXC_F_I2CM_CTRL_MSTR_RESET_EN;
Anna Bridge 186:707f6e361f3e 554 i2cm->ctrl = MXC_F_I2CM_CTRL_TX_FIFO_EN | MXC_F_I2CM_CTRL_RX_FIFO_EN;
Anna Bridge 186:707f6e361f3e 555 }
Anna Bridge 186:707f6e361f3e 556
Anna Bridge 186:707f6e361f3e 557 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 558 int I2CM_WriteTxFifo(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, const uint16_t data)
Anna Bridge 186:707f6e361f3e 559 {
Anna Bridge 186:707f6e361f3e 560 int32_t timeout = MXC_I2CM_TX_TIMEOUT;
Anna Bridge 186:707f6e361f3e 561
Anna Bridge 186:707f6e361f3e 562 // Read the TX FIFO to determine if it's full
Anna Bridge 186:707f6e361f3e 563 do {
Anna Bridge 186:707f6e361f3e 564
Anna Bridge 186:707f6e361f3e 565 // Wait for the TX FIFO to have room and check for errors
Anna Bridge 186:707f6e361f3e 566 if (i2cm->intfl & (MXC_F_I2CM_INTFL_TX_NACKED |
Anna Bridge 186:707f6e361f3e 567 MXC_F_I2CM_INTFL_TX_LOST_ARBITR)) {
Anna Bridge 186:707f6e361f3e 568
Anna Bridge 186:707f6e361f3e 569 return E_COMM_ERR;
Anna Bridge 186:707f6e361f3e 570 }
Anna Bridge 186:707f6e361f3e 571
Anna Bridge 186:707f6e361f3e 572 if((i2cm->intfl & MXC_F_I2CM_INTFL_TX_TIMEOUT) || !timeout--) {
Anna Bridge 186:707f6e361f3e 573 return E_TIME_OUT;
Anna Bridge 186:707f6e361f3e 574 }
Anna Bridge 186:707f6e361f3e 575
Anna Bridge 186:707f6e361f3e 576 } while (fifo->tx);
Anna Bridge 186:707f6e361f3e 577
Anna Bridge 186:707f6e361f3e 578 fifo->tx = data;
Anna Bridge 186:707f6e361f3e 579
Anna Bridge 186:707f6e361f3e 580 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 581 }
Anna Bridge 186:707f6e361f3e 582
Anna Bridge 186:707f6e361f3e 583 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 584 int I2CM_TxInProgress(mxc_i2cm_regs_t *i2cm)
Anna Bridge 186:707f6e361f3e 585 {
Anna Bridge 186:707f6e361f3e 586 int32_t timeout = MXC_I2CM_TX_TIMEOUT;
Anna Bridge 186:707f6e361f3e 587
Anna Bridge 186:707f6e361f3e 588 while ((i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS) && --timeout);
Anna Bridge 186:707f6e361f3e 589
Anna Bridge 186:707f6e361f3e 590 if (i2cm->intfl & (MXC_F_I2CM_INTFL_TX_NACKED |
Anna Bridge 186:707f6e361f3e 591 MXC_F_I2CM_INTFL_TX_LOST_ARBITR)) {
Anna Bridge 186:707f6e361f3e 592
Anna Bridge 186:707f6e361f3e 593 I2CM_Recover(i2cm);
Anna Bridge 186:707f6e361f3e 594 return E_COMM_ERR;
Anna Bridge 186:707f6e361f3e 595 }
Anna Bridge 186:707f6e361f3e 596
Anna Bridge 186:707f6e361f3e 597 if((i2cm->intfl & MXC_F_I2CM_INTFL_TX_TIMEOUT) && !timeout--) {
Anna Bridge 186:707f6e361f3e 598 I2CM_Recover(i2cm);
Anna Bridge 186:707f6e361f3e 599 return E_TIME_OUT;
Anna Bridge 186:707f6e361f3e 600 }
Anna Bridge 186:707f6e361f3e 601
Anna Bridge 186:707f6e361f3e 602 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 603 }
Anna Bridge 186:707f6e361f3e 604
Anna Bridge 186:707f6e361f3e 605 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 606 int I2CM_Tx(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, uint8_t addr,
Anna Bridge 186:707f6e361f3e 607 const uint8_t *data, uint32_t len, uint8_t stop)
Anna Bridge 186:707f6e361f3e 608 {
Anna Bridge 186:707f6e361f3e 609 uint32_t i;
Anna Bridge 186:707f6e361f3e 610 int error;
Anna Bridge 186:707f6e361f3e 611
Anna Bridge 186:707f6e361f3e 612 // Write the address to the TXFIFO
Anna Bridge 186:707f6e361f3e 613 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_START | (addr << 1)))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 614 return error;
Anna Bridge 186:707f6e361f3e 615 }
Anna Bridge 186:707f6e361f3e 616
Anna Bridge 186:707f6e361f3e 617 // Start the transaction if it is not currently ongoing
Anna Bridge 186:707f6e361f3e 618 if (!(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
Anna Bridge 186:707f6e361f3e 619 i2cm->trans |= MXC_F_I2CM_TRANS_TX_START;
Anna Bridge 186:707f6e361f3e 620 }
Anna Bridge 186:707f6e361f3e 621
Anna Bridge 186:707f6e361f3e 622 // Fill the FIFO
Anna Bridge 186:707f6e361f3e 623 for (i = 0; i < len; i++) {
Anna Bridge 186:707f6e361f3e 624 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_TXDATA_ACK | data[i]))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 625 return error;
Anna Bridge 186:707f6e361f3e 626 }
Anna Bridge 186:707f6e361f3e 627 }
Anna Bridge 186:707f6e361f3e 628
Anna Bridge 186:707f6e361f3e 629 // Send the stop condition
Anna Bridge 186:707f6e361f3e 630 if(stop) {
Anna Bridge 186:707f6e361f3e 631 if ((error = I2CM_WriteTxFifo(i2cm, fifo, MXC_S_I2CM_TRANS_TAG_STOP)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 632 return error;
Anna Bridge 186:707f6e361f3e 633 }
Anna Bridge 186:707f6e361f3e 634 }
Anna Bridge 186:707f6e361f3e 635
Anna Bridge 186:707f6e361f3e 636 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 637 }
Anna Bridge 186:707f6e361f3e 638
Anna Bridge 186:707f6e361f3e 639 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 640 int I2CM_Rx(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, uint8_t addr, uint8_t *data, uint32_t len, uint8_t stop)
Anna Bridge 186:707f6e361f3e 641 {
Anna Bridge 186:707f6e361f3e 642 uint32_t i = len;
Anna Bridge 186:707f6e361f3e 643 int32_t timeout;
Anna Bridge 186:707f6e361f3e 644 uint16_t temp;
Anna Bridge 186:707f6e361f3e 645 int error;
Anna Bridge 186:707f6e361f3e 646
Anna Bridge 186:707f6e361f3e 647 // Write the address to the TXFIFO
Anna Bridge 186:707f6e361f3e 648 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_START |
Anna Bridge 186:707f6e361f3e 649 (addr << 1) | I2CM_READ_BIT))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 650
Anna Bridge 186:707f6e361f3e 651 return error;
Anna Bridge 186:707f6e361f3e 652 }
Anna Bridge 186:707f6e361f3e 653
Anna Bridge 186:707f6e361f3e 654 // Write to the TXFIFO the number of bytes we want to read
Anna Bridge 186:707f6e361f3e 655 while(i > 256) {
Anna Bridge 186:707f6e361f3e 656 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | 255))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 657 return error;
Anna Bridge 186:707f6e361f3e 658 }
Anna Bridge 186:707f6e361f3e 659
Anna Bridge 186:707f6e361f3e 660 i -= 256;
Anna Bridge 186:707f6e361f3e 661 }
Anna Bridge 186:707f6e361f3e 662
Anna Bridge 186:707f6e361f3e 663 if(i > 1) {
Anna Bridge 186:707f6e361f3e 664 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | (i-2)))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 665 return error;
Anna Bridge 186:707f6e361f3e 666 }
Anna Bridge 186:707f6e361f3e 667 }
Anna Bridge 186:707f6e361f3e 668
Anna Bridge 186:707f6e361f3e 669 // Start the transaction if it is not currently ongoing
Anna Bridge 186:707f6e361f3e 670 if (!(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
Anna Bridge 186:707f6e361f3e 671 i2cm->trans |= MXC_F_I2CM_TRANS_TX_START;
Anna Bridge 186:707f6e361f3e 672 }
Anna Bridge 186:707f6e361f3e 673
Anna Bridge 186:707f6e361f3e 674
Anna Bridge 186:707f6e361f3e 675 // NACK the last read byte
Anna Bridge 186:707f6e361f3e 676 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_NACK))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 677 return error;
Anna Bridge 186:707f6e361f3e 678 }
Anna Bridge 186:707f6e361f3e 679
Anna Bridge 186:707f6e361f3e 680 // Send the stop condition
Anna Bridge 186:707f6e361f3e 681 if (stop) {
Anna Bridge 186:707f6e361f3e 682 if ((error = I2CM_WriteTxFifo(i2cm, fifo, MXC_S_I2CM_TRANS_TAG_STOP)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 683 return error;
Anna Bridge 186:707f6e361f3e 684 }
Anna Bridge 186:707f6e361f3e 685 }
Anna Bridge 186:707f6e361f3e 686
Anna Bridge 186:707f6e361f3e 687 // Get the data from the RX FIFO
Anna Bridge 186:707f6e361f3e 688 i = 0;
Anna Bridge 186:707f6e361f3e 689 while (i < len) {
Anna Bridge 186:707f6e361f3e 690
Anna Bridge 186:707f6e361f3e 691 // Wait for there to be data in the RX FIFO
Anna Bridge 186:707f6e361f3e 692 timeout = MXC_I2CM_RX_TIMEOUT;
Anna Bridge 186:707f6e361f3e 693 while (!(i2cm->intfl & MXC_F_I2CM_INTFL_RX_FIFO_NOT_EMPTY) &&
Anna Bridge 186:707f6e361f3e 694 ((i2cm->bb & MXC_F_I2CM_BB_RX_FIFO_CNT) == 0)) {
Anna Bridge 186:707f6e361f3e 695
Anna Bridge 186:707f6e361f3e 696 if((timeout-- < 0) || (i2cm->trans & MXC_F_I2CM_TRANS_TX_TIMEOUT)) {
Anna Bridge 186:707f6e361f3e 697 return E_TIME_OUT;
Anna Bridge 186:707f6e361f3e 698 }
Anna Bridge 186:707f6e361f3e 699
Anna Bridge 186:707f6e361f3e 700 if (i2cm->trans & (MXC_F_I2CM_TRANS_TX_LOST_ARBITR | MXC_F_I2CM_TRANS_TX_NACKED)) {
Anna Bridge 186:707f6e361f3e 701 return E_COMM_ERR;
Anna Bridge 186:707f6e361f3e 702 }
Anna Bridge 186:707f6e361f3e 703 }
Anna Bridge 186:707f6e361f3e 704 i2cm->intfl = MXC_F_I2CM_INTFL_RX_FIFO_NOT_EMPTY;
Anna Bridge 186:707f6e361f3e 705
Anna Bridge 186:707f6e361f3e 706 // Save the data from the RX FIFO
Anna Bridge 186:707f6e361f3e 707 temp = fifo->rx;
Anna Bridge 186:707f6e361f3e 708 if (temp & MXC_S_I2CM_RSTLS_TAG_EMPTY) {
Anna Bridge 186:707f6e361f3e 709 continue;
Anna Bridge 186:707f6e361f3e 710 }
Anna Bridge 186:707f6e361f3e 711 data[i++] = (uint8_t)temp;
Anna Bridge 186:707f6e361f3e 712 }
Anna Bridge 186:707f6e361f3e 713
Anna Bridge 186:707f6e361f3e 714 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 715 }
Anna Bridge 186:707f6e361f3e 716
Anna Bridge 186:707f6e361f3e 717 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 718 static int I2CM_CmdHandler(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, i2cm_req_t *req)
Anna Bridge 186:707f6e361f3e 719 {
Anna Bridge 186:707f6e361f3e 720 int error;
Anna Bridge 186:707f6e361f3e 721
Anna Bridge 186:707f6e361f3e 722 // Start of the command
Anna Bridge 186:707f6e361f3e 723 if(req->cmd_num == 0) {
Anna Bridge 186:707f6e361f3e 724
Anna Bridge 186:707f6e361f3e 725 // Write the address to the TXFIFO
Anna Bridge 186:707f6e361f3e 726 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_START | (req->addr << 1)))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 727 return error;
Anna Bridge 186:707f6e361f3e 728 }
Anna Bridge 186:707f6e361f3e 729
Anna Bridge 186:707f6e361f3e 730 // Start the transaction if it is not currently ongoing
Anna Bridge 186:707f6e361f3e 731 if (!(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
Anna Bridge 186:707f6e361f3e 732 i2cm->trans |= MXC_F_I2CM_TRANS_TX_START;
Anna Bridge 186:707f6e361f3e 733 }
Anna Bridge 186:707f6e361f3e 734 }
Anna Bridge 186:707f6e361f3e 735
Anna Bridge 186:707f6e361f3e 736 // Write to the FIFO until it is full or we run out of command bytes
Anna Bridge 186:707f6e361f3e 737 while((req->cmd_num < req->cmd_len) && (!fifo->tx)) {
Anna Bridge 186:707f6e361f3e 738 fifo->tx = MXC_S_I2CM_TRANS_TAG_TXDATA_ACK | req->cmd_data[req->cmd_num++];
Anna Bridge 186:707f6e361f3e 739 }
Anna Bridge 186:707f6e361f3e 740
Anna Bridge 186:707f6e361f3e 741 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 742 }
Anna Bridge 186:707f6e361f3e 743
Anna Bridge 186:707f6e361f3e 744 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 745 static int I2CM_ReadHandler(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req, int i2cm_num)
Anna Bridge 186:707f6e361f3e 746 {
Anna Bridge 186:707f6e361f3e 747 int error, cmd_remain, data_remain;
Anna Bridge 186:707f6e361f3e 748 uint16_t data;
Anna Bridge 186:707f6e361f3e 749 uint32_t temp_len, inten;
Anna Bridge 186:707f6e361f3e 750 mxc_i2cm_fifo_regs_t *fifo;
Anna Bridge 186:707f6e361f3e 751
Anna Bridge 186:707f6e361f3e 752 // Get the FIFO pointer for this I2CM
Anna Bridge 186:707f6e361f3e 753 fifo = MXC_I2CM_GET_FIFO(i2cm_num);
Anna Bridge 186:707f6e361f3e 754
Anna Bridge 186:707f6e361f3e 755 cmd_remain = req->cmd_len - req->cmd_num;
Anna Bridge 186:707f6e361f3e 756 data_remain = req->data_len - req->data_num;
Anna Bridge 186:707f6e361f3e 757
Anna Bridge 186:707f6e361f3e 758 // Process the command portion
Anna Bridge 186:707f6e361f3e 759 if((cmd_remain) && (req->cmd_data != NULL)) {
Anna Bridge 186:707f6e361f3e 760 if((error = I2CM_CmdHandler(i2cm, fifo, req)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 761 return error;
Anna Bridge 186:707f6e361f3e 762 }
Anna Bridge 186:707f6e361f3e 763
Anna Bridge 186:707f6e361f3e 764 cmd_remain = req->cmd_len - req->cmd_num;
Anna Bridge 186:707f6e361f3e 765 }
Anna Bridge 186:707f6e361f3e 766
Anna Bridge 186:707f6e361f3e 767 // Process the data portion
Anna Bridge 186:707f6e361f3e 768 if((cmd_remain == 0) && (data_remain)) {
Anna Bridge 186:707f6e361f3e 769
Anna Bridge 186:707f6e361f3e 770 // Save the data from the RXFIFO
Anna Bridge 186:707f6e361f3e 771 data = fifo->rx;
Anna Bridge 186:707f6e361f3e 772 while((req->data_num < req->data_len) && !(data & MXC_S_I2CM_RSTLS_TAG_EMPTY)) {
Anna Bridge 186:707f6e361f3e 773 req->data[req->data_num++] = data;
Anna Bridge 186:707f6e361f3e 774 data = fifo->rx;
Anna Bridge 186:707f6e361f3e 775 }
Anna Bridge 186:707f6e361f3e 776
Anna Bridge 186:707f6e361f3e 777 // Start of the data portion
Anna Bridge 186:707f6e361f3e 778 if(req->data_num == 0) {
Anna Bridge 186:707f6e361f3e 779
Anna Bridge 186:707f6e361f3e 780 temp_len = req->data_len;
Anna Bridge 186:707f6e361f3e 781
Anna Bridge 186:707f6e361f3e 782 // Write the address to the TXFIFO
Anna Bridge 186:707f6e361f3e 783 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_START |
Anna Bridge 186:707f6e361f3e 784 (req->addr << 1) | I2CM_READ_BIT))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 785
Anna Bridge 186:707f6e361f3e 786 return error;
Anna Bridge 186:707f6e361f3e 787 }
Anna Bridge 186:707f6e361f3e 788
Anna Bridge 186:707f6e361f3e 789 // Write to the TXFIFO the number of bytes we want to read
Anna Bridge 186:707f6e361f3e 790 while(temp_len > 256) {
Anna Bridge 186:707f6e361f3e 791 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | 255))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 792 return error;
Anna Bridge 186:707f6e361f3e 793 }
Anna Bridge 186:707f6e361f3e 794
Anna Bridge 186:707f6e361f3e 795 temp_len -= 256;
Anna Bridge 186:707f6e361f3e 796 }
Anna Bridge 186:707f6e361f3e 797
Anna Bridge 186:707f6e361f3e 798 if(temp_len > 1) {
Anna Bridge 186:707f6e361f3e 799 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | (temp_len-2)))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 800 return error;
Anna Bridge 186:707f6e361f3e 801 }
Anna Bridge 186:707f6e361f3e 802 }
Anna Bridge 186:707f6e361f3e 803
Anna Bridge 186:707f6e361f3e 804 // Start the transaction if it is not currently ongoing
Anna Bridge 186:707f6e361f3e 805 if (!(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
Anna Bridge 186:707f6e361f3e 806 i2cm->trans |= MXC_F_I2CM_TRANS_TX_START;
Anna Bridge 186:707f6e361f3e 807 }
Anna Bridge 186:707f6e361f3e 808
Anna Bridge 186:707f6e361f3e 809 // NACK the last read byte
Anna Bridge 186:707f6e361f3e 810 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_NACK))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 811 return error;
Anna Bridge 186:707f6e361f3e 812 }
Anna Bridge 186:707f6e361f3e 813
Anna Bridge 186:707f6e361f3e 814 // Send the stop condition
Anna Bridge 186:707f6e361f3e 815 if ((error = I2CM_WriteTxFifo(i2cm, fifo, MXC_S_I2CM_TRANS_TAG_STOP)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 816 return error;
Anna Bridge 186:707f6e361f3e 817 }
Anna Bridge 186:707f6e361f3e 818 }
Anna Bridge 186:707f6e361f3e 819 }
Anna Bridge 186:707f6e361f3e 820
Anna Bridge 186:707f6e361f3e 821 // Enable the required interrupts
Anna Bridge 186:707f6e361f3e 822 inten = MXC_F_I2CM_INTEN_TX_DONE | MXC_F_I2CM_INTEN_TX_NACKED |
Anna Bridge 186:707f6e361f3e 823 MXC_F_I2CM_INTEN_TX_LOST_ARBITR | MXC_F_I2CM_INTEN_TX_TIMEOUT;
Anna Bridge 186:707f6e361f3e 824
Anna Bridge 186:707f6e361f3e 825 if (cmd_remain) {
Anna Bridge 186:707f6e361f3e 826 inten |= (MXC_F_I2CM_INTEN_TX_FIFO_EMPTY | MXC_F_I2CM_INTEN_TX_FIFO_3Q_EMPTY);
Anna Bridge 186:707f6e361f3e 827 }
Anna Bridge 186:707f6e361f3e 828
Anna Bridge 186:707f6e361f3e 829 data_remain = req->data_len - req->data_num;
Anna Bridge 186:707f6e361f3e 830 if (data_remain > I2CM_FIFO_DEPTH_3Q) {
Anna Bridge 186:707f6e361f3e 831 inten |= MXC_F_I2CM_INTEN_RX_FIFO_3Q_FULL;
Anna Bridge 186:707f6e361f3e 832
Anna Bridge 186:707f6e361f3e 833 } else if (data_remain > I2CM_FIFO_DEPTH_2Q) {
Anna Bridge 186:707f6e361f3e 834 inten |= MXC_F_I2CM_INTEN_RX_FIFO_2Q_FULL;
Anna Bridge 186:707f6e361f3e 835
Anna Bridge 186:707f6e361f3e 836 } else if (data_remain > 0) {
Anna Bridge 186:707f6e361f3e 837 inten |= MXC_F_I2CM_INTEN_RX_FIFO_NOT_EMPTY;
Anna Bridge 186:707f6e361f3e 838 }
Anna Bridge 186:707f6e361f3e 839
Anna Bridge 186:707f6e361f3e 840 i2cm->inten = inten;
Anna Bridge 186:707f6e361f3e 841
Anna Bridge 186:707f6e361f3e 842 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 843 }
Anna Bridge 186:707f6e361f3e 844
Anna Bridge 186:707f6e361f3e 845 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 846 static int I2CM_WriteHandler(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req, int i2cm_num)
Anna Bridge 186:707f6e361f3e 847 {
Anna Bridge 186:707f6e361f3e 848 int error, cmd_remain, data_remain;
Anna Bridge 186:707f6e361f3e 849 uint32_t inten;
Anna Bridge 186:707f6e361f3e 850 mxc_i2cm_fifo_regs_t *fifo;
Anna Bridge 186:707f6e361f3e 851
Anna Bridge 186:707f6e361f3e 852 // Get the FIFO pointer for this I2CM
Anna Bridge 186:707f6e361f3e 853 fifo = MXC_I2CM_GET_FIFO(i2cm_num);
Anna Bridge 186:707f6e361f3e 854
Anna Bridge 186:707f6e361f3e 855 cmd_remain = req->cmd_len - req->cmd_num;
Anna Bridge 186:707f6e361f3e 856 data_remain = req->data_len - req->data_num;
Anna Bridge 186:707f6e361f3e 857
Anna Bridge 186:707f6e361f3e 858 // Process the command portion
Anna Bridge 186:707f6e361f3e 859 if((cmd_remain) && (req->cmd_data != NULL)) {
Anna Bridge 186:707f6e361f3e 860 if((error = I2CM_CmdHandler(i2cm, fifo, req)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 861 return error;
Anna Bridge 186:707f6e361f3e 862 }
Anna Bridge 186:707f6e361f3e 863
Anna Bridge 186:707f6e361f3e 864 cmd_remain = req->cmd_len - req->cmd_num;
Anna Bridge 186:707f6e361f3e 865 }
Anna Bridge 186:707f6e361f3e 866
Anna Bridge 186:707f6e361f3e 867 // Process the data portion
Anna Bridge 186:707f6e361f3e 868 if((cmd_remain == 0) && (data_remain)) {
Anna Bridge 186:707f6e361f3e 869
Anna Bridge 186:707f6e361f3e 870 // Start of the data portion
Anna Bridge 186:707f6e361f3e 871 if(req->data_num == 0) {
Anna Bridge 186:707f6e361f3e 872
Anna Bridge 186:707f6e361f3e 873 // Write the address to the TXFIFO
Anna Bridge 186:707f6e361f3e 874 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_START |
Anna Bridge 186:707f6e361f3e 875 (req->addr << 1)))) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 876
Anna Bridge 186:707f6e361f3e 877 return error;
Anna Bridge 186:707f6e361f3e 878 }
Anna Bridge 186:707f6e361f3e 879
Anna Bridge 186:707f6e361f3e 880 // Start the transaction if it is not currently ongoing
Anna Bridge 186:707f6e361f3e 881 if (!(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
Anna Bridge 186:707f6e361f3e 882 i2cm->trans |= MXC_F_I2CM_TRANS_TX_START;
Anna Bridge 186:707f6e361f3e 883 }
Anna Bridge 186:707f6e361f3e 884 }
Anna Bridge 186:707f6e361f3e 885
Anna Bridge 186:707f6e361f3e 886 // Write bytes to the FIFO until it's full or we run out of bytes
Anna Bridge 186:707f6e361f3e 887 while(req->data_num < req->data_len) {
Anna Bridge 186:707f6e361f3e 888 fifo->tx = MXC_S_I2CM_TRANS_TAG_TXDATA_ACK | req->data[req->data_num++];
Anna Bridge 186:707f6e361f3e 889 }
Anna Bridge 186:707f6e361f3e 890
Anna Bridge 186:707f6e361f3e 891 // Send the stop condition
Anna Bridge 186:707f6e361f3e 892 if ((error = I2CM_WriteTxFifo(i2cm, fifo, MXC_S_I2CM_TRANS_TAG_STOP)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 893 return error;
Anna Bridge 186:707f6e361f3e 894 }
Anna Bridge 186:707f6e361f3e 895 }
Anna Bridge 186:707f6e361f3e 896
Anna Bridge 186:707f6e361f3e 897 // Enable the required interrupts
Anna Bridge 186:707f6e361f3e 898 data_remain = req->data_len - req->data_num;
Anna Bridge 186:707f6e361f3e 899 inten = MXC_F_I2CM_INTEN_TX_DONE | MXC_F_I2CM_INTEN_TX_NACKED |
Anna Bridge 186:707f6e361f3e 900 MXC_F_I2CM_INTEN_TX_LOST_ARBITR | MXC_F_I2CM_INTEN_TX_TIMEOUT;
Anna Bridge 186:707f6e361f3e 901
Anna Bridge 186:707f6e361f3e 902 if(data_remain || cmd_remain) {
Anna Bridge 186:707f6e361f3e 903 inten |= (MXC_F_I2CM_INTEN_TX_FIFO_EMPTY | MXC_F_I2CM_INTEN_TX_FIFO_3Q_EMPTY);
Anna Bridge 186:707f6e361f3e 904 }
Anna Bridge 186:707f6e361f3e 905 i2cm->inten = inten;
Anna Bridge 186:707f6e361f3e 906
Anna Bridge 186:707f6e361f3e 907 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 908 }
Anna Bridge 186:707f6e361f3e 909 /**@} end of group i2cm */