mbed library sources. Supersedes mbed-src.
Fork of mbed by
targets/hal/TARGET_Atmel/TARGET_SAM_CortexM4/i2c_api.c@148:4802eb17e82b, 2016-10-17 (annotated)
- Committer:
- rodriguise
- Date:
- Mon Oct 17 18:47:01 2016 +0000
- Revision:
- 148:4802eb17e82b
- Parent:
- 107:414e9c822e99
backup
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mbed_official | 107:414e9c822e99 | 1 | /* mbed Microcontroller Library |
mbed_official | 107:414e9c822e99 | 2 | * Copyright (c) 2006-2015 ARM Limited |
mbed_official | 107:414e9c822e99 | 3 | * |
mbed_official | 107:414e9c822e99 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
mbed_official | 107:414e9c822e99 | 5 | * you may not use this file except in compliance with the License. |
mbed_official | 107:414e9c822e99 | 6 | * You may obtain a copy of the License at |
mbed_official | 107:414e9c822e99 | 7 | * |
mbed_official | 107:414e9c822e99 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
mbed_official | 107:414e9c822e99 | 9 | * |
mbed_official | 107:414e9c822e99 | 10 | * Unless required by applicable law or agreed to in writing, software |
mbed_official | 107:414e9c822e99 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
mbed_official | 107:414e9c822e99 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
mbed_official | 107:414e9c822e99 | 13 | * See the License for the specific language governing permissions and |
mbed_official | 107:414e9c822e99 | 14 | * limitations under the License. |
mbed_official | 107:414e9c822e99 | 15 | */ |
mbed_official | 107:414e9c822e99 | 16 | |
mbed_official | 107:414e9c822e99 | 17 | #include "device.h" |
mbed_official | 107:414e9c822e99 | 18 | #include "buffer.h" |
mbed_official | 107:414e9c822e99 | 19 | #include "dma_api.h" |
mbed_official | 107:414e9c822e99 | 20 | #include "i2c_api.h" |
mbed_official | 107:414e9c822e99 | 21 | #include "PeripheralPins.h" |
mbed_official | 107:414e9c822e99 | 22 | #include "twi.h" |
mbed_official | 107:414e9c822e99 | 23 | #include "pdc.h" |
mbed_official | 107:414e9c822e99 | 24 | #include "mbed_assert.h" |
mbed_official | 107:414e9c822e99 | 25 | #include "ioport.h" |
mbed_official | 107:414e9c822e99 | 26 | |
mbed_official | 107:414e9c822e99 | 27 | /** |
mbed_official | 107:414e9c822e99 | 28 | * \defgroup GeneralI2C I2C Configuration Functions |
mbed_official | 107:414e9c822e99 | 29 | * @{ |
mbed_official | 107:414e9c822e99 | 30 | */ |
mbed_official | 107:414e9c822e99 | 31 | |
mbed_official | 107:414e9c822e99 | 32 | /** TWI Bus Clock 400kHz */ |
mbed_official | 107:414e9c822e99 | 33 | extern uint8_t g_sys_init; |
mbed_official | 107:414e9c822e99 | 34 | |
mbed_official | 107:414e9c822e99 | 35 | #define TWI_CLK (400000u) |
mbed_official | 107:414e9c822e99 | 36 | |
mbed_official | 107:414e9c822e99 | 37 | #define ADDR_LENGTH 0 |
mbed_official | 107:414e9c822e99 | 38 | |
mbed_official | 107:414e9c822e99 | 39 | #define MAX_I2C 8 |
mbed_official | 107:414e9c822e99 | 40 | |
mbed_official | 107:414e9c822e99 | 41 | extern uint32_t twi_mk_addr(const uint8_t *addr, int len); |
mbed_official | 107:414e9c822e99 | 42 | |
mbed_official | 107:414e9c822e99 | 43 | void pinmap_find_i2c_info(Twi *sercombase, i2c_t *obj) |
mbed_official | 107:414e9c822e99 | 44 | { |
mbed_official | 107:414e9c822e99 | 45 | if(sercombase==TWI0) { |
mbed_official | 107:414e9c822e99 | 46 | obj->i2c.flexcom=FLEXCOM0; |
mbed_official | 107:414e9c822e99 | 47 | obj->i2c.module_number=0; |
mbed_official | 107:414e9c822e99 | 48 | obj->i2c.pdc =PDC_TWI0; |
mbed_official | 107:414e9c822e99 | 49 | obj->i2c.irq_type=FLEXCOM0_IRQn; |
mbed_official | 107:414e9c822e99 | 50 | } else if(sercombase==TWI1) { |
mbed_official | 107:414e9c822e99 | 51 | obj->i2c.flexcom=FLEXCOM1; |
mbed_official | 107:414e9c822e99 | 52 | obj->i2c.module_number=1; |
mbed_official | 107:414e9c822e99 | 53 | obj->i2c.pdc =PDC_TWI1; |
mbed_official | 107:414e9c822e99 | 54 | obj->i2c.irq_type=FLEXCOM1_IRQn; |
mbed_official | 107:414e9c822e99 | 55 | } else if(sercombase==TWI2) { |
mbed_official | 107:414e9c822e99 | 56 | obj->i2c.flexcom=FLEXCOM2; |
mbed_official | 107:414e9c822e99 | 57 | obj->i2c.module_number=2; |
mbed_official | 107:414e9c822e99 | 58 | obj->i2c.pdc =PDC_TWI2; |
mbed_official | 107:414e9c822e99 | 59 | obj->i2c.irq_type=FLEXCOM2_IRQn; |
mbed_official | 107:414e9c822e99 | 60 | } else if(sercombase==TWI3) { |
mbed_official | 107:414e9c822e99 | 61 | obj->i2c.flexcom=FLEXCOM3; |
mbed_official | 107:414e9c822e99 | 62 | obj->i2c.module_number=3; |
mbed_official | 107:414e9c822e99 | 63 | obj->i2c.pdc =PDC_TWI3; |
mbed_official | 107:414e9c822e99 | 64 | obj->i2c.irq_type=FLEXCOM3_IRQn; |
mbed_official | 107:414e9c822e99 | 65 | } else if(sercombase==TWI4) { |
mbed_official | 107:414e9c822e99 | 66 | obj->i2c.flexcom=FLEXCOM4; |
mbed_official | 107:414e9c822e99 | 67 | obj->i2c.module_number=4; |
mbed_official | 107:414e9c822e99 | 68 | obj->i2c.pdc =PDC_TWI4; |
mbed_official | 107:414e9c822e99 | 69 | obj->i2c.irq_type=FLEXCOM4_IRQn; |
mbed_official | 107:414e9c822e99 | 70 | } else if(sercombase==TWI5) { |
mbed_official | 107:414e9c822e99 | 71 | obj->i2c.flexcom=FLEXCOM5; |
mbed_official | 107:414e9c822e99 | 72 | obj->i2c.module_number=5; |
mbed_official | 107:414e9c822e99 | 73 | obj->i2c.pdc =PDC_TWI5; |
mbed_official | 107:414e9c822e99 | 74 | obj->i2c.irq_type=FLEXCOM5_IRQn; |
mbed_official | 107:414e9c822e99 | 75 | } else if(sercombase==TWI6) { |
mbed_official | 107:414e9c822e99 | 76 | obj->i2c.flexcom=FLEXCOM6; |
mbed_official | 107:414e9c822e99 | 77 | obj->i2c.module_number=6; |
mbed_official | 107:414e9c822e99 | 78 | obj->i2c.pdc =PDC_TWI6; |
mbed_official | 107:414e9c822e99 | 79 | obj->i2c.irq_type=FLEXCOM6_IRQn; |
mbed_official | 107:414e9c822e99 | 80 | } else if(sercombase==TWI7) { |
mbed_official | 107:414e9c822e99 | 81 | obj->i2c.flexcom=FLEXCOM7; |
mbed_official | 107:414e9c822e99 | 82 | obj->i2c.module_number=7; |
mbed_official | 107:414e9c822e99 | 83 | obj->i2c.pdc =PDC_TWI7; |
mbed_official | 107:414e9c822e99 | 84 | obj->i2c.irq_type=FLEXCOM7_IRQn; |
mbed_official | 107:414e9c822e99 | 85 | } else { |
mbed_official | 107:414e9c822e99 | 86 | obj->i2c.flexcom=(Flexcom *)NC; |
mbed_official | 107:414e9c822e99 | 87 | obj->i2c.module_number=0; |
mbed_official | 107:414e9c822e99 | 88 | obj->i2c.pdc =(Pdc *) NC; |
mbed_official | 107:414e9c822e99 | 89 | } |
mbed_official | 107:414e9c822e99 | 90 | } |
mbed_official | 107:414e9c822e99 | 91 | |
mbed_official | 107:414e9c822e99 | 92 | |
mbed_official | 107:414e9c822e99 | 93 | /** Initialize the I2C peripheral. It sets the default parameters for I2C |
mbed_official | 107:414e9c822e99 | 94 | * peripheral, and configure its specifieds pins. |
mbed_official | 107:414e9c822e99 | 95 | * @param obj The i2c object |
mbed_official | 107:414e9c822e99 | 96 | * @param sda The sda pin |
mbed_official | 107:414e9c822e99 | 97 | * @param scl The scl pin |
mbed_official | 107:414e9c822e99 | 98 | */ |
mbed_official | 107:414e9c822e99 | 99 | void i2c_init(i2c_t *obj, PinName sda, PinName scl) |
mbed_official | 107:414e9c822e99 | 100 | { |
mbed_official | 107:414e9c822e99 | 101 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 102 | MBED_ASSERT(sda !=NC && scl!=NC ); |
mbed_official | 107:414e9c822e99 | 103 | |
mbed_official | 107:414e9c822e99 | 104 | if (g_sys_init == 0) { |
mbed_official | 107:414e9c822e99 | 105 | sysclk_init(); |
mbed_official | 107:414e9c822e99 | 106 | board_init(); |
mbed_official | 107:414e9c822e99 | 107 | g_sys_init = 1; |
mbed_official | 107:414e9c822e99 | 108 | } |
mbed_official | 107:414e9c822e99 | 109 | |
mbed_official | 107:414e9c822e99 | 110 | |
mbed_official | 107:414e9c822e99 | 111 | Twi* sda_base = (Twi*)pinmap_peripheral(sda, PinMap_I2C_SDA); |
mbed_official | 107:414e9c822e99 | 112 | Twi* scl_base = (Twi*)pinmap_peripheral(scl, PinMap_I2C_SCL); |
mbed_official | 107:414e9c822e99 | 113 | Twi* I2cBase = (Twi*)pinmap_merge((uint32_t)sda_base, (uint32_t)scl_base); |
mbed_official | 107:414e9c822e99 | 114 | |
mbed_official | 107:414e9c822e99 | 115 | MBED_ASSERT(I2cBase !=NC ); |
mbed_official | 107:414e9c822e99 | 116 | |
mbed_official | 107:414e9c822e99 | 117 | obj->i2c.i2c_base=I2cBase; |
mbed_official | 107:414e9c822e99 | 118 | pinmap_find_i2c_info(I2cBase,obj); |
mbed_official | 107:414e9c822e99 | 119 | |
mbed_official | 107:414e9c822e99 | 120 | /* Configure I2C pins */ |
mbed_official | 107:414e9c822e99 | 121 | pin_function(sda, pinmap_find_function(sda, PinMap_I2C_SDA)); |
mbed_official | 107:414e9c822e99 | 122 | ioport_disable_pin(sda); |
mbed_official | 107:414e9c822e99 | 123 | |
mbed_official | 107:414e9c822e99 | 124 | pin_function(scl, pinmap_find_function(scl, PinMap_I2C_SCL)); |
mbed_official | 107:414e9c822e99 | 125 | ioport_disable_pin(scl); |
mbed_official | 107:414e9c822e99 | 126 | |
mbed_official | 107:414e9c822e99 | 127 | #if (SAMG55) |
mbed_official | 107:414e9c822e99 | 128 | /* Enable the peripheral and set TWI mode. */ |
mbed_official | 107:414e9c822e99 | 129 | MBED_ASSERT((int)obj->i2c.flexcom!=NC); |
mbed_official | 107:414e9c822e99 | 130 | flexcom_enable(obj->i2c.flexcom); |
mbed_official | 107:414e9c822e99 | 131 | flexcom_set_opmode(obj->i2c.flexcom, FLEXCOM_TWI); |
mbed_official | 107:414e9c822e99 | 132 | #else |
mbed_official | 107:414e9c822e99 | 133 | /* Enable the peripheral clock for TWI */ |
mbed_official | 107:414e9c822e99 | 134 | pmc_enable_periph_clk(obj->i2c.i2c_base); |
mbed_official | 107:414e9c822e99 | 135 | #endif |
mbed_official | 107:414e9c822e99 | 136 | |
mbed_official | 107:414e9c822e99 | 137 | twi_options_t twi_options; |
mbed_official | 107:414e9c822e99 | 138 | twi_options.master_clk=sysclk_get_cpu_hz(); |
mbed_official | 107:414e9c822e99 | 139 | twi_options.speed=TWI_CLK; |
mbed_official | 107:414e9c822e99 | 140 | twi_options.smbus = 0; |
mbed_official | 107:414e9c822e99 | 141 | |
mbed_official | 107:414e9c822e99 | 142 | twi_master_init(obj->i2c.i2c_base,&twi_options); |
mbed_official | 107:414e9c822e99 | 143 | |
mbed_official | 107:414e9c822e99 | 144 | obj->i2c.is_slave=false; |
mbed_official | 107:414e9c822e99 | 145 | obj->i2c.speed=TWI_CLK; |
mbed_official | 107:414e9c822e99 | 146 | obj->i2c.master_clk=twi_options.master_clk; |
mbed_official | 107:414e9c822e99 | 147 | } |
mbed_official | 107:414e9c822e99 | 148 | |
mbed_official | 107:414e9c822e99 | 149 | /** Configure the I2C frequency. |
mbed_official | 107:414e9c822e99 | 150 | * @param obj The i2c object |
mbed_official | 107:414e9c822e99 | 151 | * @param hz Frequency in Hz |
mbed_official | 107:414e9c822e99 | 152 | */ |
mbed_official | 107:414e9c822e99 | 153 | void i2c_frequency(i2c_t *obj, int hz) |
mbed_official | 107:414e9c822e99 | 154 | { |
mbed_official | 107:414e9c822e99 | 155 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 156 | if(obj->i2c.is_slave) |
mbed_official | 107:414e9c822e99 | 157 | twi_disable_slave_mode(obj->i2c.i2c_base); |
mbed_official | 107:414e9c822e99 | 158 | else |
mbed_official | 107:414e9c822e99 | 159 | twi_disable_master_mode(obj->i2c.i2c_base); |
mbed_official | 107:414e9c822e99 | 160 | |
mbed_official | 107:414e9c822e99 | 161 | twi_set_speed(obj->i2c.i2c_base,hz,obj->i2c.master_clk); |
mbed_official | 107:414e9c822e99 | 162 | |
mbed_official | 107:414e9c822e99 | 163 | if(obj->i2c.is_slave) |
mbed_official | 107:414e9c822e99 | 164 | twi_enable_slave_mode(obj->i2c.i2c_base); |
mbed_official | 107:414e9c822e99 | 165 | else |
mbed_official | 107:414e9c822e99 | 166 | twi_enable_master_mode(obj->i2c.i2c_base); |
mbed_official | 107:414e9c822e99 | 167 | } |
mbed_official | 107:414e9c822e99 | 168 | |
mbed_official | 107:414e9c822e99 | 169 | /** Send START command. |
mbed_official | 107:414e9c822e99 | 170 | * @param obj The i2c object |
mbed_official | 107:414e9c822e99 | 171 | */ |
mbed_official | 107:414e9c822e99 | 172 | int i2c_start(i2c_t *obj) |
mbed_official | 107:414e9c822e99 | 173 | { |
mbed_official | 107:414e9c822e99 | 174 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 175 | obj->i2c.i2c_base->TWI_CR = TWI_CR_START; |
mbed_official | 107:414e9c822e99 | 176 | return 0; |
mbed_official | 107:414e9c822e99 | 177 | } |
mbed_official | 107:414e9c822e99 | 178 | |
mbed_official | 107:414e9c822e99 | 179 | /** Send STOP command. |
mbed_official | 107:414e9c822e99 | 180 | * @param obj The i2c object |
mbed_official | 107:414e9c822e99 | 181 | */ |
mbed_official | 107:414e9c822e99 | 182 | int i2c_stop(i2c_t *obj) |
mbed_official | 107:414e9c822e99 | 183 | { |
mbed_official | 107:414e9c822e99 | 184 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 185 | obj->i2c.i2c_base->TWI_CR = TWI_CR_STOP; |
mbed_official | 107:414e9c822e99 | 186 | return 0; |
mbed_official | 107:414e9c822e99 | 187 | } |
mbed_official | 107:414e9c822e99 | 188 | |
mbed_official | 107:414e9c822e99 | 189 | |
mbed_official | 107:414e9c822e99 | 190 | uint32_t twi_master_read_no_stop(Twi *p_twi, twi_packet_t *p_packet, uint8_t stopena) |
mbed_official | 107:414e9c822e99 | 191 | { |
mbed_official | 107:414e9c822e99 | 192 | uint32_t status; |
mbed_official | 107:414e9c822e99 | 193 | uint32_t cnt = p_packet->length; |
mbed_official | 107:414e9c822e99 | 194 | uint8_t *buffer = p_packet->buffer; |
mbed_official | 107:414e9c822e99 | 195 | uint8_t stop_sent = 0; |
mbed_official | 107:414e9c822e99 | 196 | uint32_t timeout = TWI_TIMEOUT;; |
mbed_official | 107:414e9c822e99 | 197 | |
mbed_official | 107:414e9c822e99 | 198 | /* Check argument */ |
mbed_official | 107:414e9c822e99 | 199 | if (cnt == 0) { |
mbed_official | 107:414e9c822e99 | 200 | return TWI_INVALID_ARGUMENT; |
mbed_official | 107:414e9c822e99 | 201 | } |
mbed_official | 107:414e9c822e99 | 202 | |
mbed_official | 107:414e9c822e99 | 203 | /* Set read mode, slave address and 3 internal address byte lengths */ |
mbed_official | 107:414e9c822e99 | 204 | p_twi->TWI_MMR = 0; |
mbed_official | 107:414e9c822e99 | 205 | p_twi->TWI_MMR = TWI_MMR_MREAD | TWI_MMR_DADR(p_packet->chip) | |
mbed_official | 107:414e9c822e99 | 206 | ((p_packet->addr_length << TWI_MMR_IADRSZ_Pos) & |
mbed_official | 107:414e9c822e99 | 207 | TWI_MMR_IADRSZ_Msk); |
mbed_official | 107:414e9c822e99 | 208 | |
mbed_official | 107:414e9c822e99 | 209 | /* Send a START condition */ |
mbed_official | 107:414e9c822e99 | 210 | if ((cnt == 1) && (stopena == 1)) { |
mbed_official | 107:414e9c822e99 | 211 | p_twi->TWI_CR = TWI_CR_START | TWI_CR_STOP; |
mbed_official | 107:414e9c822e99 | 212 | stop_sent = 1; |
mbed_official | 107:414e9c822e99 | 213 | } else { |
mbed_official | 107:414e9c822e99 | 214 | p_twi->TWI_CR = TWI_CR_START; |
mbed_official | 107:414e9c822e99 | 215 | stop_sent = 0; |
mbed_official | 107:414e9c822e99 | 216 | } |
mbed_official | 107:414e9c822e99 | 217 | |
mbed_official | 107:414e9c822e99 | 218 | while (cnt > 0) { |
mbed_official | 107:414e9c822e99 | 219 | status = p_twi->TWI_SR; |
mbed_official | 107:414e9c822e99 | 220 | if (status & TWI_SR_NACK) { |
mbed_official | 107:414e9c822e99 | 221 | return TWI_RECEIVE_NACK; |
mbed_official | 107:414e9c822e99 | 222 | } |
mbed_official | 107:414e9c822e99 | 223 | |
mbed_official | 107:414e9c822e99 | 224 | if (!timeout--) { |
mbed_official | 107:414e9c822e99 | 225 | return TWI_ERROR_TIMEOUT; |
mbed_official | 107:414e9c822e99 | 226 | } |
mbed_official | 107:414e9c822e99 | 227 | |
mbed_official | 107:414e9c822e99 | 228 | /* Last byte ? */ |
mbed_official | 107:414e9c822e99 | 229 | if ((cnt == 1) && (!stop_sent) && (stopena == 1)) { |
mbed_official | 107:414e9c822e99 | 230 | p_twi->TWI_CR = TWI_CR_STOP; |
mbed_official | 107:414e9c822e99 | 231 | stop_sent = 1; |
mbed_official | 107:414e9c822e99 | 232 | } |
mbed_official | 107:414e9c822e99 | 233 | |
mbed_official | 107:414e9c822e99 | 234 | if (!(status & TWI_SR_RXRDY)) { |
mbed_official | 107:414e9c822e99 | 235 | continue; |
mbed_official | 107:414e9c822e99 | 236 | } |
mbed_official | 107:414e9c822e99 | 237 | *buffer++ = p_twi->TWI_RHR; |
mbed_official | 107:414e9c822e99 | 238 | |
mbed_official | 107:414e9c822e99 | 239 | cnt--; |
mbed_official | 107:414e9c822e99 | 240 | timeout = TWI_TIMEOUT; |
mbed_official | 107:414e9c822e99 | 241 | } |
mbed_official | 107:414e9c822e99 | 242 | if(stopena) { |
mbed_official | 107:414e9c822e99 | 243 | while (!(p_twi->TWI_SR & TWI_SR_TXCOMP)) { |
mbed_official | 107:414e9c822e99 | 244 | } |
mbed_official | 107:414e9c822e99 | 245 | } |
mbed_official | 107:414e9c822e99 | 246 | |
mbed_official | 107:414e9c822e99 | 247 | p_twi->TWI_SR; |
mbed_official | 107:414e9c822e99 | 248 | |
mbed_official | 107:414e9c822e99 | 249 | return TWI_SUCCESS; |
mbed_official | 107:414e9c822e99 | 250 | |
mbed_official | 107:414e9c822e99 | 251 | } |
mbed_official | 107:414e9c822e99 | 252 | |
mbed_official | 107:414e9c822e99 | 253 | |
mbed_official | 107:414e9c822e99 | 254 | |
mbed_official | 107:414e9c822e99 | 255 | |
mbed_official | 107:414e9c822e99 | 256 | |
mbed_official | 107:414e9c822e99 | 257 | /** Blocking reading data. |
mbed_official | 107:414e9c822e99 | 258 | * @param obj The i2c object |
mbed_official | 107:414e9c822e99 | 259 | * @param address 7-bit address (last bit is 1) |
mbed_official | 107:414e9c822e99 | 260 | * @param data The buffer for receiving |
mbed_official | 107:414e9c822e99 | 261 | * @param length Number of bytes to read |
mbed_official | 107:414e9c822e99 | 262 | * @param stop Stop to be generated after the transfer is done |
mbed_official | 107:414e9c822e99 | 263 | * @return Number of read bytes |
mbed_official | 107:414e9c822e99 | 264 | */ |
mbed_official | 107:414e9c822e99 | 265 | int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) |
mbed_official | 107:414e9c822e99 | 266 | { |
mbed_official | 107:414e9c822e99 | 267 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 268 | |
mbed_official | 107:414e9c822e99 | 269 | twi_packet_t packet; |
mbed_official | 107:414e9c822e99 | 270 | packet.chip= (address>>1) & 0x7F; |
mbed_official | 107:414e9c822e99 | 271 | packet.addr_length=ADDR_LENGTH; |
mbed_official | 107:414e9c822e99 | 272 | packet.buffer=data; |
mbed_official | 107:414e9c822e99 | 273 | packet.length=length; |
mbed_official | 107:414e9c822e99 | 274 | |
mbed_official | 107:414e9c822e99 | 275 | uint8_t status; |
mbed_official | 107:414e9c822e99 | 276 | status= twi_master_read_no_stop(obj->i2c.i2c_base, &packet, stop); |
mbed_official | 107:414e9c822e99 | 277 | |
mbed_official | 107:414e9c822e99 | 278 | if(TWI_SUCCESS==status) |
mbed_official | 107:414e9c822e99 | 279 | return length; |
mbed_official | 107:414e9c822e99 | 280 | |
mbed_official | 107:414e9c822e99 | 281 | return 0; |
mbed_official | 107:414e9c822e99 | 282 | } |
mbed_official | 107:414e9c822e99 | 283 | |
mbed_official | 107:414e9c822e99 | 284 | |
mbed_official | 107:414e9c822e99 | 285 | uint32_t twi_master_write_no_stop(Twi *p_twi, twi_packet_t *p_packet, uint8_t stopena) |
mbed_official | 107:414e9c822e99 | 286 | { |
mbed_official | 107:414e9c822e99 | 287 | uint32_t status; |
mbed_official | 107:414e9c822e99 | 288 | uint32_t cnt = p_packet->length; |
mbed_official | 107:414e9c822e99 | 289 | uint8_t *buffer = p_packet->buffer; |
mbed_official | 107:414e9c822e99 | 290 | |
mbed_official | 107:414e9c822e99 | 291 | /* Check argument */ |
mbed_official | 107:414e9c822e99 | 292 | if (cnt == 0) { |
mbed_official | 107:414e9c822e99 | 293 | return TWI_INVALID_ARGUMENT; |
mbed_official | 107:414e9c822e99 | 294 | } |
mbed_official | 107:414e9c822e99 | 295 | |
mbed_official | 107:414e9c822e99 | 296 | /* Set write mode, slave address and 3 internal address byte lengths */ |
mbed_official | 107:414e9c822e99 | 297 | p_twi->TWI_MMR = 0; |
mbed_official | 107:414e9c822e99 | 298 | p_twi->TWI_MMR = TWI_MMR_DADR(p_packet->chip) | |
mbed_official | 107:414e9c822e99 | 299 | ((p_packet->addr_length << TWI_MMR_IADRSZ_Pos) & |
mbed_official | 107:414e9c822e99 | 300 | TWI_MMR_IADRSZ_Msk); |
mbed_official | 107:414e9c822e99 | 301 | |
mbed_official | 107:414e9c822e99 | 302 | /* Send a START condition */ |
mbed_official | 107:414e9c822e99 | 303 | if ((cnt == 1) && (stopena == 1)) { |
mbed_official | 107:414e9c822e99 | 304 | p_twi->TWI_CR = TWI_CR_START | TWI_CR_STOP; |
mbed_official | 107:414e9c822e99 | 305 | } else { |
mbed_official | 107:414e9c822e99 | 306 | p_twi->TWI_CR = TWI_CR_START; |
mbed_official | 107:414e9c822e99 | 307 | } |
mbed_official | 107:414e9c822e99 | 308 | |
mbed_official | 107:414e9c822e99 | 309 | /* Send all bytes */ |
mbed_official | 107:414e9c822e99 | 310 | while (cnt > 0) { |
mbed_official | 107:414e9c822e99 | 311 | status = p_twi->TWI_SR; |
mbed_official | 107:414e9c822e99 | 312 | if (status & TWI_SR_NACK) { |
mbed_official | 107:414e9c822e99 | 313 | return TWI_RECEIVE_NACK; |
mbed_official | 107:414e9c822e99 | 314 | } |
mbed_official | 107:414e9c822e99 | 315 | |
mbed_official | 107:414e9c822e99 | 316 | if (!(status & TWI_SR_TXRDY)) { |
mbed_official | 107:414e9c822e99 | 317 | continue; |
mbed_official | 107:414e9c822e99 | 318 | } |
mbed_official | 107:414e9c822e99 | 319 | p_twi->TWI_THR = *buffer++; |
mbed_official | 107:414e9c822e99 | 320 | |
mbed_official | 107:414e9c822e99 | 321 | cnt--; |
mbed_official | 107:414e9c822e99 | 322 | } |
mbed_official | 107:414e9c822e99 | 323 | |
mbed_official | 107:414e9c822e99 | 324 | while (1) { |
mbed_official | 107:414e9c822e99 | 325 | status = p_twi->TWI_SR; |
mbed_official | 107:414e9c822e99 | 326 | if (status & TWI_SR_NACK) { |
mbed_official | 107:414e9c822e99 | 327 | return TWI_RECEIVE_NACK; |
mbed_official | 107:414e9c822e99 | 328 | } |
mbed_official | 107:414e9c822e99 | 329 | |
mbed_official | 107:414e9c822e99 | 330 | if (status & TWI_SR_TXRDY) { |
mbed_official | 107:414e9c822e99 | 331 | break; |
mbed_official | 107:414e9c822e99 | 332 | } |
mbed_official | 107:414e9c822e99 | 333 | } |
mbed_official | 107:414e9c822e99 | 334 | |
mbed_official | 107:414e9c822e99 | 335 | if (stopena) { |
mbed_official | 107:414e9c822e99 | 336 | p_twi->TWI_CR = TWI_CR_STOP; |
mbed_official | 107:414e9c822e99 | 337 | while (!(p_twi->TWI_SR & TWI_SR_TXCOMP)); |
mbed_official | 107:414e9c822e99 | 338 | } |
mbed_official | 107:414e9c822e99 | 339 | |
mbed_official | 107:414e9c822e99 | 340 | return TWI_SUCCESS; |
mbed_official | 107:414e9c822e99 | 341 | } |
mbed_official | 107:414e9c822e99 | 342 | |
mbed_official | 107:414e9c822e99 | 343 | |
mbed_official | 107:414e9c822e99 | 344 | |
mbed_official | 107:414e9c822e99 | 345 | /** Blocking sending data. |
mbed_official | 107:414e9c822e99 | 346 | * @param obj The i2c object |
mbed_official | 107:414e9c822e99 | 347 | * @param address 7-bit address (last bit is 0) |
mbed_official | 107:414e9c822e99 | 348 | * @param data The buffer for sending |
mbed_official | 107:414e9c822e99 | 349 | * @param length Number of bytes to wrte |
mbed_official | 107:414e9c822e99 | 350 | * @param stop Stop to be generated after the transfer is done |
mbed_official | 107:414e9c822e99 | 351 | * @return Number of written bytes |
mbed_official | 107:414e9c822e99 | 352 | */ |
mbed_official | 107:414e9c822e99 | 353 | int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) |
mbed_official | 107:414e9c822e99 | 354 | { |
mbed_official | 107:414e9c822e99 | 355 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 356 | |
mbed_official | 107:414e9c822e99 | 357 | twi_packet_t packet; |
mbed_official | 107:414e9c822e99 | 358 | packet.chip= (address>>1) & 0x7F; |
mbed_official | 107:414e9c822e99 | 359 | packet.addr_length=ADDR_LENGTH; |
mbed_official | 107:414e9c822e99 | 360 | packet.buffer= (void *)data; |
mbed_official | 107:414e9c822e99 | 361 | packet.length=length; |
mbed_official | 107:414e9c822e99 | 362 | |
mbed_official | 107:414e9c822e99 | 363 | uint8_t status; |
mbed_official | 107:414e9c822e99 | 364 | status= twi_master_write_no_stop(obj->i2c.i2c_base,&packet, stop); |
mbed_official | 107:414e9c822e99 | 365 | |
mbed_official | 107:414e9c822e99 | 366 | if(TWI_SUCCESS==status) |
mbed_official | 107:414e9c822e99 | 367 | return length; |
mbed_official | 107:414e9c822e99 | 368 | |
mbed_official | 107:414e9c822e99 | 369 | return 0; |
mbed_official | 107:414e9c822e99 | 370 | } |
mbed_official | 107:414e9c822e99 | 371 | |
mbed_official | 107:414e9c822e99 | 372 | /** Reset I2C peripheral. TODO: The action here. Most of the implementation sends stop(). |
mbed_official | 107:414e9c822e99 | 373 | * @param obj The i2c object |
mbed_official | 107:414e9c822e99 | 374 | */ |
mbed_official | 107:414e9c822e99 | 375 | void i2c_reset(i2c_t *obj) |
mbed_official | 107:414e9c822e99 | 376 | { |
mbed_official | 107:414e9c822e99 | 377 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 378 | twi_reset(obj->i2c.i2c_base); |
mbed_official | 107:414e9c822e99 | 379 | } |
mbed_official | 107:414e9c822e99 | 380 | |
mbed_official | 107:414e9c822e99 | 381 | /** Read one byte. |
mbed_official | 107:414e9c822e99 | 382 | * @param obj The i2c object |
mbed_official | 107:414e9c822e99 | 383 | * @param last Acknoledge |
mbed_official | 107:414e9c822e99 | 384 | * @return The read byte |
mbed_official | 107:414e9c822e99 | 385 | */ |
mbed_official | 107:414e9c822e99 | 386 | int i2c_byte_read(i2c_t *obj, int last) |
mbed_official | 107:414e9c822e99 | 387 | { |
mbed_official | 107:414e9c822e99 | 388 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 389 | if(!last) |
mbed_official | 107:414e9c822e99 | 390 | twi_enable_slave_nack(obj->i2c.i2c_base); |
mbed_official | 107:414e9c822e99 | 391 | |
mbed_official | 107:414e9c822e99 | 392 | return twi_read_byte(obj->i2c.i2c_base); |
mbed_official | 107:414e9c822e99 | 393 | } |
mbed_official | 107:414e9c822e99 | 394 | |
mbed_official | 107:414e9c822e99 | 395 | /** Write one byte. |
mbed_official | 107:414e9c822e99 | 396 | * @param obj The i2c object |
mbed_official | 107:414e9c822e99 | 397 | * @param data Byte to be written |
mbed_official | 107:414e9c822e99 | 398 | * @return 1 if NAK was received, 0 if ACK was received, 2 for timeout. |
mbed_official | 107:414e9c822e99 | 399 | */ |
mbed_official | 107:414e9c822e99 | 400 | #define ACK 0 |
mbed_official | 107:414e9c822e99 | 401 | #define NAK 1 |
mbed_official | 107:414e9c822e99 | 402 | #define TIMEOUT 2 |
mbed_official | 107:414e9c822e99 | 403 | |
mbed_official | 107:414e9c822e99 | 404 | int i2c_byte_write(i2c_t *obj, int data) |
mbed_official | 107:414e9c822e99 | 405 | { |
mbed_official | 107:414e9c822e99 | 406 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 407 | twi_write_byte(obj->i2c.i2c_base,data); |
mbed_official | 107:414e9c822e99 | 408 | |
mbed_official | 107:414e9c822e99 | 409 | uint32_t timeout = TWI_TIMEOUT; |
mbed_official | 107:414e9c822e99 | 410 | while (timeout--) { |
mbed_official | 107:414e9c822e99 | 411 | uint32_t status = obj->i2c.i2c_base->TWI_SR; |
mbed_official | 107:414e9c822e99 | 412 | if (status & TWI_SR_NACK) { |
mbed_official | 107:414e9c822e99 | 413 | return NAK; |
mbed_official | 107:414e9c822e99 | 414 | } |
mbed_official | 107:414e9c822e99 | 415 | |
mbed_official | 107:414e9c822e99 | 416 | if (status & TWI_SR_TXRDY) { |
mbed_official | 107:414e9c822e99 | 417 | return ACK; |
mbed_official | 107:414e9c822e99 | 418 | } |
mbed_official | 107:414e9c822e99 | 419 | |
mbed_official | 107:414e9c822e99 | 420 | if (timeout<1) { |
mbed_official | 107:414e9c822e99 | 421 | return TIMEOUT; |
mbed_official | 107:414e9c822e99 | 422 | } |
mbed_official | 107:414e9c822e99 | 423 | } |
mbed_official | 107:414e9c822e99 | 424 | |
mbed_official | 107:414e9c822e99 | 425 | return ACK; |
mbed_official | 107:414e9c822e99 | 426 | } |
mbed_official | 107:414e9c822e99 | 427 | |
mbed_official | 107:414e9c822e99 | 428 | /**@}*/ |
mbed_official | 107:414e9c822e99 | 429 | |
mbed_official | 107:414e9c822e99 | 430 | #if DEVICE_I2CSLAVE |
mbed_official | 107:414e9c822e99 | 431 | |
mbed_official | 107:414e9c822e99 | 432 | /** |
mbed_official | 107:414e9c822e99 | 433 | * \defgroup SynchI2C Synchronous I2C Hardware Abstraction Layer for slave |
mbed_official | 107:414e9c822e99 | 434 | * @{ |
mbed_official | 107:414e9c822e99 | 435 | */ |
mbed_official | 107:414e9c822e99 | 436 | |
mbed_official | 107:414e9c822e99 | 437 | /** Configure I2C as slave or master. |
mbed_official | 107:414e9c822e99 | 438 | * @param obj The I2C object |
mbed_official | 107:414e9c822e99 | 439 | * @return non-zero if a value is available |
mbed_official | 107:414e9c822e99 | 440 | */ |
mbed_official | 107:414e9c822e99 | 441 | void i2c_slave_mode(i2c_t *obj, int enable_slave) |
mbed_official | 107:414e9c822e99 | 442 | { |
mbed_official | 107:414e9c822e99 | 443 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 444 | /* Disable TWI interrupts */ |
mbed_official | 107:414e9c822e99 | 445 | obj->i2c.i2c_base->TWI_IDR = ~0UL; |
mbed_official | 107:414e9c822e99 | 446 | obj->i2c.i2c_base->TWI_SR; |
mbed_official | 107:414e9c822e99 | 447 | |
mbed_official | 107:414e9c822e99 | 448 | /* Reset TWI */ |
mbed_official | 107:414e9c822e99 | 449 | twi_reset(obj->i2c.i2c_base); |
mbed_official | 107:414e9c822e99 | 450 | |
mbed_official | 107:414e9c822e99 | 451 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 452 | if(enable_slave) |
mbed_official | 107:414e9c822e99 | 453 | twi_enable_slave_mode(obj->i2c.i2c_base); |
mbed_official | 107:414e9c822e99 | 454 | else |
mbed_official | 107:414e9c822e99 | 455 | twi_enable_master_mode(obj->i2c.i2c_base); |
mbed_official | 107:414e9c822e99 | 456 | } |
mbed_official | 107:414e9c822e99 | 457 | |
mbed_official | 107:414e9c822e99 | 458 | /** Check to see if the I2C slave has been addressed. |
mbed_official | 107:414e9c822e99 | 459 | * @param obj The I2C object |
mbed_official | 107:414e9c822e99 | 460 | * @return The status - 1 - read addresses, 2 - write to all slaves, |
mbed_official | 107:414e9c822e99 | 461 | * 3 write addressed, 0 - the slave has not been addressed |
mbed_official | 107:414e9c822e99 | 462 | */ |
mbed_official | 107:414e9c822e99 | 463 | int i2c_slave_receive(i2c_t *obj) |
mbed_official | 107:414e9c822e99 | 464 | { |
mbed_official | 107:414e9c822e99 | 465 | uint32_t status = obj->i2c.i2c_base->TWI_SR; |
mbed_official | 107:414e9c822e99 | 466 | if((status & TWI_SR_SVACC)) { |
mbed_official | 107:414e9c822e99 | 467 | if(status & TWI_SR_SVREAD) |
mbed_official | 107:414e9c822e99 | 468 | return 1; |
mbed_official | 107:414e9c822e99 | 469 | else |
mbed_official | 107:414e9c822e99 | 470 | return 3; |
mbed_official | 107:414e9c822e99 | 471 | } |
mbed_official | 107:414e9c822e99 | 472 | return 0; |
mbed_official | 107:414e9c822e99 | 473 | } |
mbed_official | 107:414e9c822e99 | 474 | |
mbed_official | 107:414e9c822e99 | 475 | |
mbed_official | 107:414e9c822e99 | 476 | uint32_t twi_slave_read_n(Twi *p_twi, uint8_t *p_data, int length) |
mbed_official | 107:414e9c822e99 | 477 | { |
mbed_official | 107:414e9c822e99 | 478 | uint32_t status, cnt = 0; |
mbed_official | 107:414e9c822e99 | 479 | |
mbed_official | 107:414e9c822e99 | 480 | do { |
mbed_official | 107:414e9c822e99 | 481 | status = p_twi->TWI_SR; |
mbed_official | 107:414e9c822e99 | 482 | if (status & TWI_SR_SVACC) { |
mbed_official | 107:414e9c822e99 | 483 | if (!(status & (TWI_SR_GACC| TWI_SR_SVREAD )) && |
mbed_official | 107:414e9c822e99 | 484 | (status & TWI_SR_RXRDY) |
mbed_official | 107:414e9c822e99 | 485 | ) { |
mbed_official | 107:414e9c822e99 | 486 | *p_data++ = (uint8_t) p_twi->TWI_RHR; |
mbed_official | 107:414e9c822e99 | 487 | cnt++; |
mbed_official | 107:414e9c822e99 | 488 | if(cnt>=length) break; |
mbed_official | 107:414e9c822e99 | 489 | } |
mbed_official | 107:414e9c822e99 | 490 | } else if ((status & (TWI_SR_EOSACC | TWI_SR_TXCOMP)) |
mbed_official | 107:414e9c822e99 | 491 | == (TWI_SR_EOSACC | TWI_SR_TXCOMP)) { |
mbed_official | 107:414e9c822e99 | 492 | break; |
mbed_official | 107:414e9c822e99 | 493 | } |
mbed_official | 107:414e9c822e99 | 494 | } while (1); |
mbed_official | 107:414e9c822e99 | 495 | |
mbed_official | 107:414e9c822e99 | 496 | return cnt; |
mbed_official | 107:414e9c822e99 | 497 | } |
mbed_official | 107:414e9c822e99 | 498 | |
mbed_official | 107:414e9c822e99 | 499 | /** Read I2C slave. |
mbed_official | 107:414e9c822e99 | 500 | * @param obj The I2C object |
mbed_official | 107:414e9c822e99 | 501 | * @return non-zero if a value is available |
mbed_official | 107:414e9c822e99 | 502 | */ |
mbed_official | 107:414e9c822e99 | 503 | int i2c_slave_read(i2c_t *obj, char *data, int length) |
mbed_official | 107:414e9c822e99 | 504 | { |
mbed_official | 107:414e9c822e99 | 505 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 506 | int read= twi_slave_read_n(obj->i2c.i2c_base,(uint8_t *) data,length); |
mbed_official | 107:414e9c822e99 | 507 | return read; |
mbed_official | 107:414e9c822e99 | 508 | } |
mbed_official | 107:414e9c822e99 | 509 | |
mbed_official | 107:414e9c822e99 | 510 | |
mbed_official | 107:414e9c822e99 | 511 | uint32_t twi_slave_write_n(Twi *p_twi, uint8_t *p_data, int length) |
mbed_official | 107:414e9c822e99 | 512 | { |
mbed_official | 107:414e9c822e99 | 513 | uint32_t status, cnt = 0; |
mbed_official | 107:414e9c822e99 | 514 | |
mbed_official | 107:414e9c822e99 | 515 | do { |
mbed_official | 107:414e9c822e99 | 516 | status = p_twi->TWI_SR; |
mbed_official | 107:414e9c822e99 | 517 | if (status & TWI_SR_SVACC) { |
mbed_official | 107:414e9c822e99 | 518 | if ((status & TWI_SR_SVREAD) && !(status & TWI_SR_GACC) && |
mbed_official | 107:414e9c822e99 | 519 | (status & TWI_SR_TXRDY)) { |
mbed_official | 107:414e9c822e99 | 520 | p_twi->TWI_THR = *p_data++; |
mbed_official | 107:414e9c822e99 | 521 | cnt++; |
mbed_official | 107:414e9c822e99 | 522 | if(cnt>=length) break; |
mbed_official | 107:414e9c822e99 | 523 | } |
mbed_official | 107:414e9c822e99 | 524 | } else if ((status & (TWI_SR_EOSACC | TWI_SR_TXCOMP)) |
mbed_official | 107:414e9c822e99 | 525 | == (TWI_SR_EOSACC | TWI_SR_TXCOMP)) { |
mbed_official | 107:414e9c822e99 | 526 | break; |
mbed_official | 107:414e9c822e99 | 527 | } |
mbed_official | 107:414e9c822e99 | 528 | } while (1); |
mbed_official | 107:414e9c822e99 | 529 | |
mbed_official | 107:414e9c822e99 | 530 | return cnt; |
mbed_official | 107:414e9c822e99 | 531 | } |
mbed_official | 107:414e9c822e99 | 532 | |
mbed_official | 107:414e9c822e99 | 533 | |
mbed_official | 107:414e9c822e99 | 534 | /** Write I2C as slave. |
mbed_official | 107:414e9c822e99 | 535 | * @param obj The I2C object |
mbed_official | 107:414e9c822e99 | 536 | * @return non-zero if a value is available |
mbed_official | 107:414e9c822e99 | 537 | */ |
mbed_official | 107:414e9c822e99 | 538 | int i2c_slave_write(i2c_t *obj, const char *data, int length) |
mbed_official | 107:414e9c822e99 | 539 | { |
mbed_official | 107:414e9c822e99 | 540 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 541 | int write= twi_slave_write_n(obj->i2c.i2c_base, (uint8_t *) data,length); |
mbed_official | 107:414e9c822e99 | 542 | return write; |
mbed_official | 107:414e9c822e99 | 543 | } |
mbed_official | 107:414e9c822e99 | 544 | |
mbed_official | 107:414e9c822e99 | 545 | /** Configure I2C address. |
mbed_official | 107:414e9c822e99 | 546 | * @param obj The I2C object |
mbed_official | 107:414e9c822e99 | 547 | * @param idx Currently not used |
mbed_official | 107:414e9c822e99 | 548 | * @param address The address to be set |
mbed_official | 107:414e9c822e99 | 549 | * @param mask Currently not used |
mbed_official | 107:414e9c822e99 | 550 | */ |
mbed_official | 107:414e9c822e99 | 551 | void i2c_slave_address(i2c_t *obj, int idx/*not used*/, uint32_t address, uint32_t mask) |
mbed_official | 107:414e9c822e99 | 552 | { |
mbed_official | 107:414e9c822e99 | 553 | MBED_ASSERT(obj); |
mbed_official | 107:414e9c822e99 | 554 | twi_set_slave_addr(obj->i2c.i2c_base, (address>>1)); |
mbed_official | 107:414e9c822e99 | 555 | } |
mbed_official | 107:414e9c822e99 | 556 | |
mbed_official | 107:414e9c822e99 | 557 | #endif |
mbed_official | 107:414e9c822e99 | 558 | |
mbed_official | 107:414e9c822e99 | 559 | /**@}*/ |
mbed_official | 107:414e9c822e99 | 560 | |
mbed_official | 107:414e9c822e99 | 561 | #if DEVICE_I2C_ASYNCH |
mbed_official | 107:414e9c822e99 | 562 | |
mbed_official | 107:414e9c822e99 | 563 | /** |
mbed_official | 107:414e9c822e99 | 564 | * \defgroup AsynchI2C Asynchronous I2C Hardware Abstraction Layer |
mbed_official | 107:414e9c822e99 | 565 | * @{ |
mbed_official | 107:414e9c822e99 | 566 | */ |
mbed_official | 107:414e9c822e99 | 567 | |
mbed_official | 107:414e9c822e99 | 568 | /** Start i2c asynchronous transfer. |
mbed_official | 107:414e9c822e99 | 569 | * @param obj The I2C object |
mbed_official | 107:414e9c822e99 | 570 | * @param tx The buffer to send |
mbed_official | 107:414e9c822e99 | 571 | * @param tx_length The number of words to transmit |
mbed_official | 107:414e9c822e99 | 572 | * @param rx The buffer to receive |
mbed_official | 107:414e9c822e99 | 573 | * @param rx_length The number of words to receive |
mbed_official | 107:414e9c822e99 | 574 | * @param address The address to be set - 7bit or 9 bit |
mbed_official | 107:414e9c822e99 | 575 | * @param stop If true, stop will be generated after the transfer is done |
mbed_official | 107:414e9c822e99 | 576 | * @param handler The I2C IRQ handler to be set |
mbed_official | 107:414e9c822e99 | 577 | * @param hint DMA hint usage |
mbed_official | 107:414e9c822e99 | 578 | */ |
mbed_official | 107:414e9c822e99 | 579 | #warning "Only DMA async supported by I2C master transfer" |
mbed_official | 107:414e9c822e99 | 580 | |
mbed_official | 107:414e9c822e99 | 581 | void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint /*Not Used*/) |
mbed_official | 107:414e9c822e99 | 582 | { |
mbed_official | 107:414e9c822e99 | 583 | uint32_t pdcenable=0; |
mbed_official | 107:414e9c822e99 | 584 | |
mbed_official | 107:414e9c822e99 | 585 | if(address) { |
mbed_official | 107:414e9c822e99 | 586 | twi_packet_t pdc_packet; |
mbed_official | 107:414e9c822e99 | 587 | pdc_packet.chip=(address>>1) & 0x7F; |
mbed_official | 107:414e9c822e99 | 588 | pdc_packet.addr_length=ADDR_LENGTH; |
mbed_official | 107:414e9c822e99 | 589 | |
mbed_official | 107:414e9c822e99 | 590 | /* Set write mode, slave address and 3 internal address byte lengths */ |
mbed_official | 107:414e9c822e99 | 591 | obj->i2c.i2c_base->TWI_MMR = 0; |
mbed_official | 107:414e9c822e99 | 592 | obj->i2c.i2c_base->TWI_MMR = TWI_MMR_DADR(pdc_packet.chip) | |
mbed_official | 107:414e9c822e99 | 593 | ((pdc_packet.addr_length << TWI_MMR_IADRSZ_Pos) & |
mbed_official | 107:414e9c822e99 | 594 | TWI_MMR_IADRSZ_Msk); |
mbed_official | 107:414e9c822e99 | 595 | } |
mbed_official | 107:414e9c822e99 | 596 | |
mbed_official | 107:414e9c822e99 | 597 | if(tx) { |
mbed_official | 107:414e9c822e99 | 598 | pdc_packet_t pdc_packet_tx; |
mbed_official | 107:414e9c822e99 | 599 | pdc_packet_tx.ul_addr=(uint32_t)tx; |
mbed_official | 107:414e9c822e99 | 600 | pdc_packet_tx.ul_size=tx_length; |
mbed_official | 107:414e9c822e99 | 601 | |
mbed_official | 107:414e9c822e99 | 602 | pdcenable|=PERIPH_PTCR_TXTEN; |
mbed_official | 107:414e9c822e99 | 603 | /* Configure PDC for data send */ |
mbed_official | 107:414e9c822e99 | 604 | pdc_tx_init(obj->i2c.pdc, &pdc_packet_tx, NULL); |
mbed_official | 107:414e9c822e99 | 605 | } |
mbed_official | 107:414e9c822e99 | 606 | |
mbed_official | 107:414e9c822e99 | 607 | if(rx) { |
mbed_official | 107:414e9c822e99 | 608 | obj->i2c.i2c_base->TWI_MMR |= TWI_MMR_MREAD; |
mbed_official | 107:414e9c822e99 | 609 | pdc_rx_clear_cnt(obj->i2c.pdc); |
mbed_official | 107:414e9c822e99 | 610 | pdc_packet_t pdc_packet_rx; |
mbed_official | 107:414e9c822e99 | 611 | pdc_packet_rx.ul_addr=(uint32_t)rx; |
mbed_official | 107:414e9c822e99 | 612 | pdc_packet_rx.ul_size=rx_length; |
mbed_official | 107:414e9c822e99 | 613 | pdcenable|=PERIPH_PTCR_RXTEN; |
mbed_official | 107:414e9c822e99 | 614 | |
mbed_official | 107:414e9c822e99 | 615 | /* Configure PDC for data receive */ |
mbed_official | 107:414e9c822e99 | 616 | pdc_rx_init(obj->i2c.pdc, &pdc_packet_rx, NULL); |
mbed_official | 107:414e9c822e99 | 617 | } |
mbed_official | 107:414e9c822e99 | 618 | |
mbed_official | 107:414e9c822e99 | 619 | obj->i2c.dma_usage=hint; |
mbed_official | 107:414e9c822e99 | 620 | obj->i2c.event=event; |
mbed_official | 107:414e9c822e99 | 621 | obj->i2c.stop=stop; |
mbed_official | 107:414e9c822e99 | 622 | obj->i2c.address=address; |
mbed_official | 107:414e9c822e99 | 623 | |
mbed_official | 107:414e9c822e99 | 624 | NVIC_ClearPendingIRQ(obj->i2c.irq_type); |
mbed_official | 107:414e9c822e99 | 625 | NVIC_DisableIRQ(obj->i2c.irq_type); |
mbed_official | 107:414e9c822e99 | 626 | NVIC_SetVector(obj->i2c.irq_type,handler); |
mbed_official | 107:414e9c822e99 | 627 | NVIC_EnableIRQ(obj->i2c.irq_type); |
mbed_official | 107:414e9c822e99 | 628 | |
mbed_official | 107:414e9c822e99 | 629 | /* Enable TWI IRQ */ |
mbed_official | 107:414e9c822e99 | 630 | twi_enable_interrupt(obj->i2c.i2c_base, TWI_IER_RXBUFF| TWI_IER_TXBUFE | TWI_IER_UNRE | TWI_IER_OVRE | TWI_IER_PECERR); |
mbed_official | 107:414e9c822e99 | 631 | |
mbed_official | 107:414e9c822e99 | 632 | /* Enable PDC transfers */ |
mbed_official | 107:414e9c822e99 | 633 | pdc_enable_transfer(obj->i2c.pdc, pdcenable ); |
mbed_official | 107:414e9c822e99 | 634 | |
mbed_official | 107:414e9c822e99 | 635 | } |
mbed_official | 107:414e9c822e99 | 636 | |
mbed_official | 107:414e9c822e99 | 637 | /** The asynchronous IRQ handler |
mbed_official | 107:414e9c822e99 | 638 | * @param obj The I2C object which holds the transfer information |
mbed_official | 107:414e9c822e99 | 639 | * @return event flags if a transfer termination condition was met or 0 otherwise. |
mbed_official | 107:414e9c822e99 | 640 | */ |
mbed_official | 107:414e9c822e99 | 641 | uint32_t i2c_irq_handler_asynch(i2c_t *obj) |
mbed_official | 107:414e9c822e99 | 642 | { |
mbed_official | 107:414e9c822e99 | 643 | uint32_t event=0; |
mbed_official | 107:414e9c822e99 | 644 | |
mbed_official | 107:414e9c822e99 | 645 | if(obj->i2c.stop) { |
mbed_official | 107:414e9c822e99 | 646 | i2c_stop(obj); |
mbed_official | 107:414e9c822e99 | 647 | } |
mbed_official | 107:414e9c822e99 | 648 | |
mbed_official | 107:414e9c822e99 | 649 | // Data transferred via DMA |
mbed_official | 107:414e9c822e99 | 650 | if((obj->i2c.i2c_base->TWI_SR & TWI_IER_TXBUFE)) { |
mbed_official | 107:414e9c822e99 | 651 | twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_TXBUFE | TWI_IDR_UNRE | TWI_IDR_OVRE | TWI_IDR_PECERR); |
mbed_official | 107:414e9c822e99 | 652 | if(obj->i2c.event | I2C_EVENT_TRANSFER_COMPLETE) |
mbed_official | 107:414e9c822e99 | 653 | event |=I2C_EVENT_TRANSFER_COMPLETE; |
mbed_official | 107:414e9c822e99 | 654 | } |
mbed_official | 107:414e9c822e99 | 655 | |
mbed_official | 107:414e9c822e99 | 656 | if((obj->i2c.i2c_base->TWI_SR & TWI_IER_RXBUFF)) { |
mbed_official | 107:414e9c822e99 | 657 | twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_RXBUFF | TWI_IDR_UNRE | TWI_IDR_OVRE | TWI_IDR_PECERR); |
mbed_official | 107:414e9c822e99 | 658 | if(obj->i2c.event | I2C_EVENT_TRANSFER_COMPLETE) |
mbed_official | 107:414e9c822e99 | 659 | event |=I2C_EVENT_TRANSFER_COMPLETE; |
mbed_official | 107:414e9c822e99 | 660 | } |
mbed_official | 107:414e9c822e99 | 661 | |
mbed_official | 107:414e9c822e99 | 662 | if(obj->i2c.i2c_base->TWI_SR & TWI_IER_NACK) { |
mbed_official | 107:414e9c822e99 | 663 | if(obj->i2c.event | I2C_EVENT_TRANSFER_EARLY_NACK) |
mbed_official | 107:414e9c822e99 | 664 | event |=I2C_EVENT_TRANSFER_EARLY_NACK; |
mbed_official | 107:414e9c822e99 | 665 | } |
mbed_official | 107:414e9c822e99 | 666 | |
mbed_official | 107:414e9c822e99 | 667 | |
mbed_official | 107:414e9c822e99 | 668 | if((obj->i2c.i2c_base->TWI_SR & TWI_IER_UNRE) || (obj->i2c.i2c_base->TWI_SR & TWI_IER_OVRE) || (obj->i2c.i2c_base->TWI_SR & TWI_IER_PECERR) || (obj->i2c.i2c_base->TWI_SR & TWI_SR_TOUT) ) { |
mbed_official | 107:414e9c822e99 | 669 | if((obj->i2c.event | I2C_EVENT_ERROR)) |
mbed_official | 107:414e9c822e99 | 670 | event |=I2C_EVENT_ERROR; |
mbed_official | 107:414e9c822e99 | 671 | |
mbed_official | 107:414e9c822e99 | 672 | if(obj->i2c.address) { |
mbed_official | 107:414e9c822e99 | 673 | uint8_t status= twi_probe(obj->i2c.i2c_base,obj->i2c.address); |
mbed_official | 107:414e9c822e99 | 674 | if((obj->i2c.event | I2C_EVENT_ERROR_NO_SLAVE) && (status!=TWI_SUCCESS) ) |
mbed_official | 107:414e9c822e99 | 675 | event |=I2C_EVENT_ERROR_NO_SLAVE; |
mbed_official | 107:414e9c822e99 | 676 | } |
mbed_official | 107:414e9c822e99 | 677 | } |
mbed_official | 107:414e9c822e99 | 678 | |
mbed_official | 107:414e9c822e99 | 679 | return event; |
mbed_official | 107:414e9c822e99 | 680 | } |
mbed_official | 107:414e9c822e99 | 681 | |
mbed_official | 107:414e9c822e99 | 682 | /** Attempts to determine if I2C peripheral is already in use. |
mbed_official | 107:414e9c822e99 | 683 | * @param obj The I2C object |
mbed_official | 107:414e9c822e99 | 684 | * @return non-zero if the I2C module is active or zero if it is not |
mbed_official | 107:414e9c822e99 | 685 | */ |
mbed_official | 107:414e9c822e99 | 686 | uint8_t i2c_active(i2c_t *obj) |
mbed_official | 107:414e9c822e99 | 687 | { |
mbed_official | 107:414e9c822e99 | 688 | |
mbed_official | 107:414e9c822e99 | 689 | if(obj->i2c.i2c_base->TWI_SR & TWI_SR_ENDTX && obj->i2c.i2c_base->TWI_SR & TWI_SR_ENDRX) |
mbed_official | 107:414e9c822e99 | 690 | return 0; |
mbed_official | 107:414e9c822e99 | 691 | |
mbed_official | 107:414e9c822e99 | 692 | return 1; |
mbed_official | 107:414e9c822e99 | 693 | |
mbed_official | 107:414e9c822e99 | 694 | } |
mbed_official | 107:414e9c822e99 | 695 | |
mbed_official | 107:414e9c822e99 | 696 | /** Abort ongoing asynchronous transaction. |
mbed_official | 107:414e9c822e99 | 697 | * @param obj The I2C object |
mbed_official | 107:414e9c822e99 | 698 | */ |
mbed_official | 107:414e9c822e99 | 699 | void i2c_abort_asynch(i2c_t *obj) |
mbed_official | 107:414e9c822e99 | 700 | { |
mbed_official | 107:414e9c822e99 | 701 | /* Disable PDC transfers */ |
mbed_official | 107:414e9c822e99 | 702 | pdc_disable_transfer(obj->i2c.pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS); |
mbed_official | 107:414e9c822e99 | 703 | |
mbed_official | 107:414e9c822e99 | 704 | /* Clear PDC buffer receive counter */ |
mbed_official | 107:414e9c822e99 | 705 | pdc_rx_clear_cnt(obj->i2c.pdc); |
mbed_official | 107:414e9c822e99 | 706 | |
mbed_official | 107:414e9c822e99 | 707 | /* Disable I2C IRQ */ |
mbed_official | 107:414e9c822e99 | 708 | twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_TXBUFE); |
mbed_official | 107:414e9c822e99 | 709 | twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_RXBUFF); |
mbed_official | 107:414e9c822e99 | 710 | |
mbed_official | 107:414e9c822e99 | 711 | /* Disable I2C interrupt */ |
mbed_official | 107:414e9c822e99 | 712 | NVIC_DisableIRQ(obj->i2c.irq_type); |
mbed_official | 107:414e9c822e99 | 713 | } |
mbed_official | 107:414e9c822e99 | 714 | |
mbed_official | 107:414e9c822e99 | 715 | #endif |