mbed library sources. Supersedes mbed-src. Edited target satm32f446 for user USART3 pins
Fork of mbed-dev by
targets/TARGET_Maxim/TARGET_MAX32620C/mxc/i2cm.c@186:707f6e361f3e, 2018-06-22 (annotated)
- Committer:
- Anna Bridge
- Date:
- Fri Jun 22 16:45:37 2018 +0100
- Revision:
- 186:707f6e361f3e
mbed-dev library. Release version 162
Who changed what in which revision?
User | Revision | Line number | New 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 */ |