This is the final version of Mini Gateway for Automation and Security desgined for Renesas GR Peach Design Contest

Dependencies:   GR-PEACH_video GraphicsFramework HTTPServer R_BSP mbed-rpc mbed-rtos Socket lwip-eth lwip-sys lwip FATFileSystem

Fork of mbed-os-example-mbed5-blinky by mbed-os-examples

Committer:
vipinranka
Date:
Wed Jan 11 11:41:30 2017 +0000
Revision:
12:9a20164dcc47
This is the final version MGAS Project for Renesas GR Peach Design Contest

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vipinranka 12:9a20164dcc47 1 /*******************************************************************************
vipinranka 12:9a20164dcc47 2 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
vipinranka 12:9a20164dcc47 3 *
vipinranka 12:9a20164dcc47 4 * Permission is hereby granted, free of charge, to any person obtaining a
vipinranka 12:9a20164dcc47 5 * copy of this software and associated documentation files (the "Software"),
vipinranka 12:9a20164dcc47 6 * to deal in the Software without restriction, including without limitation
vipinranka 12:9a20164dcc47 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
vipinranka 12:9a20164dcc47 8 * and/or sell copies of the Software, and to permit persons to whom the
vipinranka 12:9a20164dcc47 9 * Software is furnished to do so, subject to the following conditions:
vipinranka 12:9a20164dcc47 10 *
vipinranka 12:9a20164dcc47 11 * The above copyright notice and this permission notice shall be included
vipinranka 12:9a20164dcc47 12 * in all copies or substantial portions of the Software.
vipinranka 12:9a20164dcc47 13 *
vipinranka 12:9a20164dcc47 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
vipinranka 12:9a20164dcc47 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
vipinranka 12:9a20164dcc47 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
vipinranka 12:9a20164dcc47 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
vipinranka 12:9a20164dcc47 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
vipinranka 12:9a20164dcc47 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
vipinranka 12:9a20164dcc47 20 * OTHER DEALINGS IN THE SOFTWARE.
vipinranka 12:9a20164dcc47 21 *
vipinranka 12:9a20164dcc47 22 * Except as contained in this notice, the name of Maxim Integrated
vipinranka 12:9a20164dcc47 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
vipinranka 12:9a20164dcc47 24 * Products, Inc. Branding Policy.
vipinranka 12:9a20164dcc47 25 *
vipinranka 12:9a20164dcc47 26 * The mere transfer of this software does not imply any licenses
vipinranka 12:9a20164dcc47 27 * of trade secrets, proprietary technology, copyrights, patents,
vipinranka 12:9a20164dcc47 28 * trademarks, maskwork rights, or any other form of intellectual
vipinranka 12:9a20164dcc47 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
vipinranka 12:9a20164dcc47 30 * ownership rights.
vipinranka 12:9a20164dcc47 31 *******************************************************************************
vipinranka 12:9a20164dcc47 32 */
vipinranka 12:9a20164dcc47 33
vipinranka 12:9a20164dcc47 34 #include "mbed_assert.h"
vipinranka 12:9a20164dcc47 35 #include "i2c_api.h"
vipinranka 12:9a20164dcc47 36 #include "cmsis.h"
vipinranka 12:9a20164dcc47 37 #include "i2cm_regs.h"
vipinranka 12:9a20164dcc47 38 #include "clkman_regs.h"
vipinranka 12:9a20164dcc47 39 #include "ioman_regs.h"
vipinranka 12:9a20164dcc47 40 #include "PeripheralPins.h"
vipinranka 12:9a20164dcc47 41
vipinranka 12:9a20164dcc47 42 #define I2C_SLAVE_ADDR_READ_BIT 0x0001
vipinranka 12:9a20164dcc47 43
vipinranka 12:9a20164dcc47 44 #ifndef MXC_I2CM_TX_TIMEOUT
vipinranka 12:9a20164dcc47 45 #define MXC_I2CM_TX_TIMEOUT 0x5000
vipinranka 12:9a20164dcc47 46 #endif
vipinranka 12:9a20164dcc47 47
vipinranka 12:9a20164dcc47 48 #ifndef MXC_I2CM_RX_TIMEOUT
vipinranka 12:9a20164dcc47 49 #define MXC_I2CM_RX_TIMEOUT 0x5000
vipinranka 12:9a20164dcc47 50 #endif
vipinranka 12:9a20164dcc47 51
vipinranka 12:9a20164dcc47 52 typedef enum {
vipinranka 12:9a20164dcc47 53 /** 100KHz */
vipinranka 12:9a20164dcc47 54 MXC_E_I2CM_SPEED_100KHZ = 0,
vipinranka 12:9a20164dcc47 55 /** 400KHz */
vipinranka 12:9a20164dcc47 56 MXC_E_I2CM_SPEED_400KHZ
vipinranka 12:9a20164dcc47 57 } i2cm_speed_t;
vipinranka 12:9a20164dcc47 58
vipinranka 12:9a20164dcc47 59 /* Clock divider lookup table */
vipinranka 12:9a20164dcc47 60 static const uint32_t clk_div_table[2][8] = {
vipinranka 12:9a20164dcc47 61 /* MXC_E_I2CM_SPEED_100KHZ */
vipinranka 12:9a20164dcc47 62 {
vipinranka 12:9a20164dcc47 63 /* 0: 12MHz */ ((6 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
vipinranka 12:9a20164dcc47 64 (17 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
vipinranka 12:9a20164dcc47 65 (72 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
vipinranka 12:9a20164dcc47 66 /* 1: 24MHz */ ((12 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
vipinranka 12:9a20164dcc47 67 (38 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
vipinranka 12:9a20164dcc47 68 (144 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
vipinranka 12:9a20164dcc47 69 /* 2: */ 0, /* not supported */
vipinranka 12:9a20164dcc47 70 /* 3: 48MHz */ ((24 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
vipinranka 12:9a20164dcc47 71 (80 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
vipinranka 12:9a20164dcc47 72 (288 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
vipinranka 12:9a20164dcc47 73 /* 4: */ 0, /* not supported */
vipinranka 12:9a20164dcc47 74 /* 5: */ 0, /* not supported */
vipinranka 12:9a20164dcc47 75 /* 6: */ 0, /* not supported */
vipinranka 12:9a20164dcc47 76 /* 7: 96MHz */ ((48 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
vipinranka 12:9a20164dcc47 77 (164 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
vipinranka 12:9a20164dcc47 78 (576 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
vipinranka 12:9a20164dcc47 79 },
vipinranka 12:9a20164dcc47 80 /* MXC_E_I2CM_SPEED_400KHZ */
vipinranka 12:9a20164dcc47 81 {
vipinranka 12:9a20164dcc47 82 /* 0: 12MHz */ ((2 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
vipinranka 12:9a20164dcc47 83 (1 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
vipinranka 12:9a20164dcc47 84 (18 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
vipinranka 12:9a20164dcc47 85 /* 1: 24MHz */ ((3 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
vipinranka 12:9a20164dcc47 86 (5 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
vipinranka 12:9a20164dcc47 87 (36 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
vipinranka 12:9a20164dcc47 88 /* 2: */ 0, /* not supported */
vipinranka 12:9a20164dcc47 89 /* 3: 48MHz */ ((6 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
vipinranka 12:9a20164dcc47 90 (15 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
vipinranka 12:9a20164dcc47 91 (72 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
vipinranka 12:9a20164dcc47 92 /* 4: */ 0, /* not supported */
vipinranka 12:9a20164dcc47 93 /* 5: */ 0, /* not supported */
vipinranka 12:9a20164dcc47 94 /* 6: */ 0, /* not supported */
vipinranka 12:9a20164dcc47 95 /* 7: 96MHz */ ((12 << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
vipinranka 12:9a20164dcc47 96 (33 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
vipinranka 12:9a20164dcc47 97 (144 << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS)),
vipinranka 12:9a20164dcc47 98 },
vipinranka 12:9a20164dcc47 99 };
vipinranka 12:9a20164dcc47 100
vipinranka 12:9a20164dcc47 101 void i2c_init(i2c_t *obj, PinName sda, PinName scl)
vipinranka 12:9a20164dcc47 102 {
vipinranka 12:9a20164dcc47 103 // determine the I2C to use
vipinranka 12:9a20164dcc47 104 I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
vipinranka 12:9a20164dcc47 105 I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
vipinranka 12:9a20164dcc47 106 mxc_i2cm_regs_t *i2c = (mxc_i2cm_regs_t*)pinmap_merge(i2c_sda, i2c_scl);
vipinranka 12:9a20164dcc47 107 MBED_ASSERT((int)i2c != NC);
vipinranka 12:9a20164dcc47 108
vipinranka 12:9a20164dcc47 109 obj->i2c = i2c;
vipinranka 12:9a20164dcc47 110 obj->fifos = (mxc_i2cm_fifo_regs_t*)MXC_I2CM_GET_BASE_FIFO(MXC_I2CM_GET_IDX(i2c));
vipinranka 12:9a20164dcc47 111 obj->start_pending = 0;
vipinranka 12:9a20164dcc47 112 obj->stop_pending = 0;
vipinranka 12:9a20164dcc47 113
vipinranka 12:9a20164dcc47 114 // configure the pins
vipinranka 12:9a20164dcc47 115 pinmap_pinout(sda, PinMap_I2C_SDA);
vipinranka 12:9a20164dcc47 116 pinmap_pinout(scl, PinMap_I2C_SCL);
vipinranka 12:9a20164dcc47 117
vipinranka 12:9a20164dcc47 118 // enable the clock
vipinranka 12:9a20164dcc47 119 MXC_CLKMAN->sys_clk_ctrl_9_i2cm = MXC_S_CLKMAN_CLK_SCALE_DIV_1;
vipinranka 12:9a20164dcc47 120
vipinranka 12:9a20164dcc47 121 // reset module
vipinranka 12:9a20164dcc47 122 i2c->ctrl = MXC_F_I2CM_CTRL_MSTR_RESET_EN;
vipinranka 12:9a20164dcc47 123 i2c->ctrl = 0;
vipinranka 12:9a20164dcc47 124
vipinranka 12:9a20164dcc47 125 // set default frequency at 100k
vipinranka 12:9a20164dcc47 126 i2c_frequency(obj, 100000);
vipinranka 12:9a20164dcc47 127
vipinranka 12:9a20164dcc47 128 // set timeout to 255 ms and turn on the auto-stop option
vipinranka 12:9a20164dcc47 129 i2c->timeout = (0xFF << MXC_F_I2CM_TIMEOUT_TX_TIMEOUT_POS) | MXC_F_I2CM_TIMEOUT_AUTO_STOP_EN;
vipinranka 12:9a20164dcc47 130
vipinranka 12:9a20164dcc47 131 // enable tx_fifo and rx_fifo
vipinranka 12:9a20164dcc47 132 i2c->ctrl |= (MXC_F_I2CM_CTRL_TX_FIFO_EN | MXC_F_I2CM_CTRL_RX_FIFO_EN);
vipinranka 12:9a20164dcc47 133 }
vipinranka 12:9a20164dcc47 134
vipinranka 12:9a20164dcc47 135 void i2c_frequency(i2c_t *obj, int hz)
vipinranka 12:9a20164dcc47 136 {
vipinranka 12:9a20164dcc47 137 // compute clock array index
vipinranka 12:9a20164dcc47 138 // (96Mhz/12M) -1 = 7
vipinranka 12:9a20164dcc47 139 // (48Mhz/12M) -1 = 3
vipinranka 12:9a20164dcc47 140 // (24Mhz/12M) -1 = 1
vipinranka 12:9a20164dcc47 141 // (12Mhz/12M) -1 = 0
vipinranka 12:9a20164dcc47 142 int clki = (SystemCoreClock / 12000000) - 1;
vipinranka 12:9a20164dcc47 143
vipinranka 12:9a20164dcc47 144 // get clock divider settings from lookup table
vipinranka 12:9a20164dcc47 145 if ((hz < 400000) && (clk_div_table[MXC_E_I2CM_SPEED_100KHZ][clki] > 0)) {
vipinranka 12:9a20164dcc47 146 obj->i2c->fs_clk_div = clk_div_table[MXC_E_I2CM_SPEED_100KHZ][clki];
vipinranka 12:9a20164dcc47 147 } else if ((hz >= 400000) && (clk_div_table[MXC_E_I2CM_SPEED_400KHZ][clki] > 0)) {
vipinranka 12:9a20164dcc47 148 obj->i2c->fs_clk_div = clk_div_table[MXC_E_I2CM_SPEED_400KHZ][clki];
vipinranka 12:9a20164dcc47 149 }
vipinranka 12:9a20164dcc47 150 }
vipinranka 12:9a20164dcc47 151
vipinranka 12:9a20164dcc47 152 static int write_tx_fifo(i2c_t *obj, const uint16_t data)
vipinranka 12:9a20164dcc47 153 {
vipinranka 12:9a20164dcc47 154 int timeout = MXC_I2CM_TX_TIMEOUT;
vipinranka 12:9a20164dcc47 155
vipinranka 12:9a20164dcc47 156 while (*obj->fifos->trans) {
vipinranka 12:9a20164dcc47 157 uint32_t intfl = obj->i2c->intfl;
vipinranka 12:9a20164dcc47 158 if (intfl & MXC_F_I2CM_INTFL_TX_NACKED) {
vipinranka 12:9a20164dcc47 159 return I2C_ERROR_NO_SLAVE;
vipinranka 12:9a20164dcc47 160 }
vipinranka 12:9a20164dcc47 161 if (!timeout || (intfl & (MXC_F_I2CM_INTFL_TX_TIMEOUT | MXC_F_I2CM_INTFL_TX_LOST_ARBITR))) {
vipinranka 12:9a20164dcc47 162 return I2C_ERROR_BUS_BUSY;
vipinranka 12:9a20164dcc47 163 }
vipinranka 12:9a20164dcc47 164 timeout--;
vipinranka 12:9a20164dcc47 165 }
vipinranka 12:9a20164dcc47 166 *obj->fifos->trans = data;
vipinranka 12:9a20164dcc47 167
vipinranka 12:9a20164dcc47 168 return 0;
vipinranka 12:9a20164dcc47 169 }
vipinranka 12:9a20164dcc47 170
vipinranka 12:9a20164dcc47 171 static int wait_tx_in_progress(i2c_t *obj)
vipinranka 12:9a20164dcc47 172 {
vipinranka 12:9a20164dcc47 173 int timeout = MXC_I2CM_TX_TIMEOUT;
vipinranka 12:9a20164dcc47 174
vipinranka 12:9a20164dcc47 175 while ((obj->i2c->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS) && --timeout);
vipinranka 12:9a20164dcc47 176
vipinranka 12:9a20164dcc47 177 uint32_t intfl = obj->i2c->intfl;
vipinranka 12:9a20164dcc47 178
vipinranka 12:9a20164dcc47 179 if (intfl & MXC_F_I2CM_INTFL_TX_NACKED) {
vipinranka 12:9a20164dcc47 180 i2c_reset(obj);
vipinranka 12:9a20164dcc47 181 return I2C_ERROR_NO_SLAVE;
vipinranka 12:9a20164dcc47 182 }
vipinranka 12:9a20164dcc47 183
vipinranka 12:9a20164dcc47 184 if (!timeout || (intfl & (MXC_F_I2CM_INTFL_TX_TIMEOUT | MXC_F_I2CM_INTFL_TX_LOST_ARBITR))) {
vipinranka 12:9a20164dcc47 185 i2c_reset(obj);
vipinranka 12:9a20164dcc47 186 return I2C_ERROR_BUS_BUSY;
vipinranka 12:9a20164dcc47 187 }
vipinranka 12:9a20164dcc47 188
vipinranka 12:9a20164dcc47 189 return 0;
vipinranka 12:9a20164dcc47 190 }
vipinranka 12:9a20164dcc47 191
vipinranka 12:9a20164dcc47 192 int i2c_start(i2c_t *obj)
vipinranka 12:9a20164dcc47 193 {
vipinranka 12:9a20164dcc47 194 obj->start_pending = 1;
vipinranka 12:9a20164dcc47 195 return 0;
vipinranka 12:9a20164dcc47 196 }
vipinranka 12:9a20164dcc47 197
vipinranka 12:9a20164dcc47 198 int i2c_stop(i2c_t *obj)
vipinranka 12:9a20164dcc47 199 {
vipinranka 12:9a20164dcc47 200 obj->start_pending = 0;
vipinranka 12:9a20164dcc47 201 write_tx_fifo(obj, MXC_S_I2CM_TRANS_TAG_STOP);
vipinranka 12:9a20164dcc47 202
vipinranka 12:9a20164dcc47 203 return wait_tx_in_progress(obj);
vipinranka 12:9a20164dcc47 204 }
vipinranka 12:9a20164dcc47 205
vipinranka 12:9a20164dcc47 206 void i2c_reset(i2c_t *obj)
vipinranka 12:9a20164dcc47 207 {
vipinranka 12:9a20164dcc47 208 obj->i2c->ctrl = MXC_F_I2CM_CTRL_MSTR_RESET_EN;
vipinranka 12:9a20164dcc47 209 obj->i2c->intfl = 0x3FF; // clear all interrupts
vipinranka 12:9a20164dcc47 210 obj->i2c->ctrl = MXC_F_I2CM_CTRL_TX_FIFO_EN | MXC_F_I2CM_CTRL_RX_FIFO_EN;
vipinranka 12:9a20164dcc47 211 obj->start_pending = 0;
vipinranka 12:9a20164dcc47 212 }
vipinranka 12:9a20164dcc47 213
vipinranka 12:9a20164dcc47 214 int i2c_byte_write(i2c_t *obj, int data)
vipinranka 12:9a20164dcc47 215 {
vipinranka 12:9a20164dcc47 216 int err;
vipinranka 12:9a20164dcc47 217
vipinranka 12:9a20164dcc47 218 // clear all interrupts
vipinranka 12:9a20164dcc47 219 obj->i2c->intfl = 0x3FF;
vipinranka 12:9a20164dcc47 220
vipinranka 12:9a20164dcc47 221 if (obj->start_pending) {
vipinranka 12:9a20164dcc47 222 obj->start_pending = 0;
vipinranka 12:9a20164dcc47 223 data = (data & 0xFF) | MXC_S_I2CM_TRANS_TAG_START;
vipinranka 12:9a20164dcc47 224 } else {
vipinranka 12:9a20164dcc47 225 data = (data & 0xFF) | MXC_S_I2CM_TRANS_TAG_TXDATA_ACK;
vipinranka 12:9a20164dcc47 226 }
vipinranka 12:9a20164dcc47 227
vipinranka 12:9a20164dcc47 228 if ((err = write_tx_fifo(obj, data)) != 0) {
vipinranka 12:9a20164dcc47 229 return err;
vipinranka 12:9a20164dcc47 230 }
vipinranka 12:9a20164dcc47 231
vipinranka 12:9a20164dcc47 232 obj->i2c->trans |= MXC_F_I2CM_TRANS_TX_START;
vipinranka 12:9a20164dcc47 233
vipinranka 12:9a20164dcc47 234 // Wait for the FIFO to be empty
vipinranka 12:9a20164dcc47 235 while (!(obj->i2c->intfl & MXC_F_I2CM_INTFL_TX_FIFO_EMPTY));
vipinranka 12:9a20164dcc47 236
vipinranka 12:9a20164dcc47 237 if (obj->i2c->intfl & MXC_F_I2CM_INTFL_TX_NACKED) {
vipinranka 12:9a20164dcc47 238 i2c_reset(obj);
vipinranka 12:9a20164dcc47 239 return 0;
vipinranka 12:9a20164dcc47 240 }
vipinranka 12:9a20164dcc47 241
vipinranka 12:9a20164dcc47 242 if (obj->i2c->intfl & (MXC_F_I2CM_INTFL_TX_TIMEOUT | MXC_F_I2CM_INTFL_TX_LOST_ARBITR)) {
vipinranka 12:9a20164dcc47 243 i2c_reset(obj);
vipinranka 12:9a20164dcc47 244 return 2;
vipinranka 12:9a20164dcc47 245 }
vipinranka 12:9a20164dcc47 246
vipinranka 12:9a20164dcc47 247 return 1;
vipinranka 12:9a20164dcc47 248 }
vipinranka 12:9a20164dcc47 249
vipinranka 12:9a20164dcc47 250 int i2c_byte_read(i2c_t *obj, int last)
vipinranka 12:9a20164dcc47 251 {
vipinranka 12:9a20164dcc47 252 uint16_t fifo_value;
vipinranka 12:9a20164dcc47 253 int err;
vipinranka 12:9a20164dcc47 254
vipinranka 12:9a20164dcc47 255 // clear all interrupts
vipinranka 12:9a20164dcc47 256 obj->i2c->intfl = 0x3FF;
vipinranka 12:9a20164dcc47 257
vipinranka 12:9a20164dcc47 258 if (last) {
vipinranka 12:9a20164dcc47 259 fifo_value = MXC_S_I2CM_TRANS_TAG_RXDATA_NACK;
vipinranka 12:9a20164dcc47 260 } else {
vipinranka 12:9a20164dcc47 261 fifo_value = MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT;
vipinranka 12:9a20164dcc47 262 }
vipinranka 12:9a20164dcc47 263
vipinranka 12:9a20164dcc47 264 if ((err = write_tx_fifo(obj, fifo_value)) != 0) {
vipinranka 12:9a20164dcc47 265 i2c_reset(obj);
vipinranka 12:9a20164dcc47 266 return err;
vipinranka 12:9a20164dcc47 267 }
vipinranka 12:9a20164dcc47 268
vipinranka 12:9a20164dcc47 269 obj->i2c->trans |= MXC_F_I2CM_TRANS_TX_START;
vipinranka 12:9a20164dcc47 270
vipinranka 12:9a20164dcc47 271 int timeout = MXC_I2CM_RX_TIMEOUT;
vipinranka 12:9a20164dcc47 272 while (!(obj->i2c->intfl & MXC_F_I2CM_INTFL_RX_FIFO_NOT_EMPTY) &&
vipinranka 12:9a20164dcc47 273 (!(obj->i2c->bb & MXC_F_I2CM_BB_RX_FIFO_CNT))) {
vipinranka 12:9a20164dcc47 274 if ((--timeout < 0) || (obj->i2c->trans & (MXC_F_I2CM_TRANS_TX_TIMEOUT |
vipinranka 12:9a20164dcc47 275 MXC_F_I2CM_TRANS_TX_LOST_ARBITR | MXC_F_I2CM_TRANS_TX_NACKED))) {
vipinranka 12:9a20164dcc47 276 break;
vipinranka 12:9a20164dcc47 277 }
vipinranka 12:9a20164dcc47 278 }
vipinranka 12:9a20164dcc47 279
vipinranka 12:9a20164dcc47 280 if (obj->i2c->intfl & MXC_F_I2CM_INTFL_RX_FIFO_NOT_EMPTY) {
vipinranka 12:9a20164dcc47 281 obj->i2c->intfl = MXC_F_I2CM_INTFL_RX_FIFO_NOT_EMPTY;
vipinranka 12:9a20164dcc47 282 return *obj->fifos->rslts;
vipinranka 12:9a20164dcc47 283 }
vipinranka 12:9a20164dcc47 284
vipinranka 12:9a20164dcc47 285 i2c_reset(obj);
vipinranka 12:9a20164dcc47 286
vipinranka 12:9a20164dcc47 287 return -1;
vipinranka 12:9a20164dcc47 288 }
vipinranka 12:9a20164dcc47 289
vipinranka 12:9a20164dcc47 290 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
vipinranka 12:9a20164dcc47 291 {
vipinranka 12:9a20164dcc47 292 int err, retval = 0;
vipinranka 12:9a20164dcc47 293 int i;
vipinranka 12:9a20164dcc47 294
vipinranka 12:9a20164dcc47 295 if (!(obj->stop_pending) && (obj->i2c->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
vipinranka 12:9a20164dcc47 296 return 0;
vipinranka 12:9a20164dcc47 297 }
vipinranka 12:9a20164dcc47 298
vipinranka 12:9a20164dcc47 299 // clear all interrupts
vipinranka 12:9a20164dcc47 300 obj->i2c->intfl = 0x3FF;
vipinranka 12:9a20164dcc47 301
vipinranka 12:9a20164dcc47 302 // write the address to the fifo
vipinranka 12:9a20164dcc47 303 if ((err = write_tx_fifo(obj, (MXC_S_I2CM_TRANS_TAG_START | address))) != 0) { // start + addr (write)
vipinranka 12:9a20164dcc47 304 i2c_reset(obj);
vipinranka 12:9a20164dcc47 305 return err;
vipinranka 12:9a20164dcc47 306 }
vipinranka 12:9a20164dcc47 307 obj->start_pending = 0;
vipinranka 12:9a20164dcc47 308
vipinranka 12:9a20164dcc47 309 // start the transaction
vipinranka 12:9a20164dcc47 310 obj->i2c->trans |= MXC_F_I2CM_TRANS_TX_START;
vipinranka 12:9a20164dcc47 311
vipinranka 12:9a20164dcc47 312 // load as much of the cmd into the FIFO as possible
vipinranka 12:9a20164dcc47 313 for (i = 0; i < length; i++) {
vipinranka 12:9a20164dcc47 314 if ((err = write_tx_fifo(obj, (MXC_S_I2CM_TRANS_TAG_TXDATA_ACK | data[i]))) != 0) { // cmd (expect ACK)
vipinranka 12:9a20164dcc47 315 retval = (retval ? retval : err);
vipinranka 12:9a20164dcc47 316 break;
vipinranka 12:9a20164dcc47 317 }
vipinranka 12:9a20164dcc47 318 }
vipinranka 12:9a20164dcc47 319
vipinranka 12:9a20164dcc47 320 if (stop) {
vipinranka 12:9a20164dcc47 321 obj->stop_pending = 0;
vipinranka 12:9a20164dcc47 322 if ((err = write_tx_fifo(obj, MXC_S_I2CM_TRANS_TAG_STOP)) != 0) { // stop condition
vipinranka 12:9a20164dcc47 323 retval = (retval ? retval : err);
vipinranka 12:9a20164dcc47 324 }
vipinranka 12:9a20164dcc47 325
vipinranka 12:9a20164dcc47 326 if ((err = wait_tx_in_progress(obj)) != 0) {
vipinranka 12:9a20164dcc47 327 retval = (retval ? retval : err);
vipinranka 12:9a20164dcc47 328 }
vipinranka 12:9a20164dcc47 329 } else {
vipinranka 12:9a20164dcc47 330 obj->stop_pending = 1;
vipinranka 12:9a20164dcc47 331 int timeout = MXC_I2CM_TX_TIMEOUT;
vipinranka 12:9a20164dcc47 332 // Wait for TX fifo to be empty
vipinranka 12:9a20164dcc47 333 while (!(obj->i2c->intfl & MXC_F_I2CM_INTFL_TX_FIFO_EMPTY) && timeout--);
vipinranka 12:9a20164dcc47 334 }
vipinranka 12:9a20164dcc47 335
vipinranka 12:9a20164dcc47 336 if (retval == 0) {
vipinranka 12:9a20164dcc47 337 return length;
vipinranka 12:9a20164dcc47 338 }
vipinranka 12:9a20164dcc47 339
vipinranka 12:9a20164dcc47 340 i2c_reset(obj);
vipinranka 12:9a20164dcc47 341
vipinranka 12:9a20164dcc47 342 return retval;
vipinranka 12:9a20164dcc47 343 }
vipinranka 12:9a20164dcc47 344
vipinranka 12:9a20164dcc47 345 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
vipinranka 12:9a20164dcc47 346 {
vipinranka 12:9a20164dcc47 347 int err, retval = 0;
vipinranka 12:9a20164dcc47 348 int i = length;
vipinranka 12:9a20164dcc47 349 int timeout;
vipinranka 12:9a20164dcc47 350
vipinranka 12:9a20164dcc47 351 if (!(obj->stop_pending) && (obj->i2c->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
vipinranka 12:9a20164dcc47 352 return 0;
vipinranka 12:9a20164dcc47 353 }
vipinranka 12:9a20164dcc47 354
vipinranka 12:9a20164dcc47 355 // clear all interrupts
vipinranka 12:9a20164dcc47 356 obj->i2c->intfl = 0x3FF;
vipinranka 12:9a20164dcc47 357
vipinranka 12:9a20164dcc47 358 // start + addr (read)
vipinranka 12:9a20164dcc47 359 if ((retval = write_tx_fifo(obj, (MXC_S_I2CM_TRANS_TAG_START | address | I2C_SLAVE_ADDR_READ_BIT))) != 0) {
vipinranka 12:9a20164dcc47 360 goto read_done;
vipinranka 12:9a20164dcc47 361 }
vipinranka 12:9a20164dcc47 362 obj->start_pending = 0;
vipinranka 12:9a20164dcc47 363
vipinranka 12:9a20164dcc47 364 while (i > 256) {
vipinranka 12:9a20164dcc47 365 if ((retval = write_tx_fifo(obj, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | 255))) != 0) {
vipinranka 12:9a20164dcc47 366 goto read_done;
vipinranka 12:9a20164dcc47 367 }
vipinranka 12:9a20164dcc47 368 i -= 256;
vipinranka 12:9a20164dcc47 369 }
vipinranka 12:9a20164dcc47 370
vipinranka 12:9a20164dcc47 371 if (i > 1) {
vipinranka 12:9a20164dcc47 372 if ((retval = write_tx_fifo(obj, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | (i - 2)))) != 0) {
vipinranka 12:9a20164dcc47 373 goto read_done;
vipinranka 12:9a20164dcc47 374 }
vipinranka 12:9a20164dcc47 375 }
vipinranka 12:9a20164dcc47 376
vipinranka 12:9a20164dcc47 377 // start the transaction
vipinranka 12:9a20164dcc47 378 obj->i2c->trans |= MXC_F_I2CM_TRANS_TX_START;
vipinranka 12:9a20164dcc47 379
vipinranka 12:9a20164dcc47 380 if ((retval = write_tx_fifo(obj, MXC_S_I2CM_TRANS_TAG_RXDATA_NACK)) != 0) { // NACK last data byte
vipinranka 12:9a20164dcc47 381 goto read_done;
vipinranka 12:9a20164dcc47 382 }
vipinranka 12:9a20164dcc47 383
vipinranka 12:9a20164dcc47 384 if (stop) {
vipinranka 12:9a20164dcc47 385 if ((retval = write_tx_fifo(obj, MXC_S_I2CM_TRANS_TAG_STOP)) != 0) { // stop condition
vipinranka 12:9a20164dcc47 386 goto read_done;
vipinranka 12:9a20164dcc47 387 }
vipinranka 12:9a20164dcc47 388 }
vipinranka 12:9a20164dcc47 389
vipinranka 12:9a20164dcc47 390 timeout = MXC_I2CM_RX_TIMEOUT;
vipinranka 12:9a20164dcc47 391 i = 0;
vipinranka 12:9a20164dcc47 392 while (i < length) {
vipinranka 12:9a20164dcc47 393 while (!(obj->i2c->intfl & MXC_F_I2CM_INTFL_RX_FIFO_NOT_EMPTY) &&
vipinranka 12:9a20164dcc47 394 (!(obj->i2c->bb & MXC_F_I2CM_BB_RX_FIFO_CNT))) {
vipinranka 12:9a20164dcc47 395 if ((--timeout < 0) || (obj->i2c->trans & (MXC_F_I2CM_TRANS_TX_TIMEOUT |
vipinranka 12:9a20164dcc47 396 MXC_F_I2CM_TRANS_TX_LOST_ARBITR | MXC_F_I2CM_TRANS_TX_NACKED))) {
vipinranka 12:9a20164dcc47 397 retval = -3;
vipinranka 12:9a20164dcc47 398 goto read_done;
vipinranka 12:9a20164dcc47 399 }
vipinranka 12:9a20164dcc47 400 }
vipinranka 12:9a20164dcc47 401
vipinranka 12:9a20164dcc47 402 timeout = MXC_I2CM_RX_TIMEOUT;
vipinranka 12:9a20164dcc47 403
vipinranka 12:9a20164dcc47 404 obj->i2c->intfl = MXC_F_I2CM_INTFL_RX_FIFO_NOT_EMPTY;
vipinranka 12:9a20164dcc47 405
vipinranka 12:9a20164dcc47 406 uint16_t temp = *obj->fifos->rslts;
vipinranka 12:9a20164dcc47 407
vipinranka 12:9a20164dcc47 408 if (temp & MXC_S_I2CM_RSTLS_TAG_EMPTY) {
vipinranka 12:9a20164dcc47 409 continue;
vipinranka 12:9a20164dcc47 410 }
vipinranka 12:9a20164dcc47 411 data[i++] = (uint8_t) temp;
vipinranka 12:9a20164dcc47 412 }
vipinranka 12:9a20164dcc47 413
vipinranka 12:9a20164dcc47 414 read_done:
vipinranka 12:9a20164dcc47 415
vipinranka 12:9a20164dcc47 416 if (stop) {
vipinranka 12:9a20164dcc47 417 obj->stop_pending = 0;
vipinranka 12:9a20164dcc47 418 if ((err = wait_tx_in_progress(obj)) != 0) {
vipinranka 12:9a20164dcc47 419 retval = (retval ? retval : err);
vipinranka 12:9a20164dcc47 420 }
vipinranka 12:9a20164dcc47 421 } else {
vipinranka 12:9a20164dcc47 422 obj->stop_pending = 1;
vipinranka 12:9a20164dcc47 423 }
vipinranka 12:9a20164dcc47 424
vipinranka 12:9a20164dcc47 425 if (retval == 0) {
vipinranka 12:9a20164dcc47 426 return length;
vipinranka 12:9a20164dcc47 427 }
vipinranka 12:9a20164dcc47 428
vipinranka 12:9a20164dcc47 429 i2c_reset(obj);
vipinranka 12:9a20164dcc47 430
vipinranka 12:9a20164dcc47 431 return retval;
vipinranka 12:9a20164dcc47 432 }