mbed library sources. Supersedes mbed-src. Fixed broken STM32F1xx RTC on rtc_api.c

Dependents:   Nucleo_F103RB_RTC_battery_bkup_pwr_off_okay

Fork of mbed-dev by mbed official

Committer:
maxxir
Date:
Tue Nov 07 16:46:29 2017 +0000
Revision:
177:619788de047e
Parent:
149:156823d33999
To fix broken RTC on Nucleo_F103RB / STM32F103 BluePill etc..;  Used direct RTC register manipulation for STM32F1xx;  rtc_read() && rtc_write()  (native rtc_init() - works good);  also added stub for non-working on STM32F1xx rtc_read_subseconds().

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /* mbed Microcontroller Library
<> 144:ef7eb2e8f9f7 2 * Copyright (c) 2006-2015 ARM Limited
<> 144:ef7eb2e8f9f7 3 *
<> 144:ef7eb2e8f9f7 4 * Licensed under the Apache License, Version 2.0 (the "License");
<> 144:ef7eb2e8f9f7 5 * you may not use this file except in compliance with the License.
<> 144:ef7eb2e8f9f7 6 * You may obtain a copy of the License at
<> 144:ef7eb2e8f9f7 7 *
<> 144:ef7eb2e8f9f7 8 * http://www.apache.org/licenses/LICENSE-2.0
<> 144:ef7eb2e8f9f7 9 *
<> 144:ef7eb2e8f9f7 10 * Unless required by applicable law or agreed to in writing, software
<> 144:ef7eb2e8f9f7 11 * distributed under the License is distributed on an "AS IS" BASIS,
<> 144:ef7eb2e8f9f7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<> 144:ef7eb2e8f9f7 13 * See the License for the specific language governing permissions and
<> 144:ef7eb2e8f9f7 14 * limitations under the License.
<> 144:ef7eb2e8f9f7 15 */
<> 144:ef7eb2e8f9f7 16 #include "mbed_assert.h"
<> 144:ef7eb2e8f9f7 17 #include "i2c_api.h"
<> 144:ef7eb2e8f9f7 18
<> 144:ef7eb2e8f9f7 19 #include "cmsis.h"
<> 144:ef7eb2e8f9f7 20 #include "pinmap.h"
<> 144:ef7eb2e8f9f7 21 #include "clk_freqs.h"
<> 144:ef7eb2e8f9f7 22 #include "PeripheralPins.h"
<> 144:ef7eb2e8f9f7 23
<> 144:ef7eb2e8f9f7 24 static const uint16_t ICR[0x40] = {
<> 144:ef7eb2e8f9f7 25 20, 22, 24, 26, 28,
<> 144:ef7eb2e8f9f7 26 30, 34, 40, 28, 32,
<> 144:ef7eb2e8f9f7 27 36, 40, 44, 48, 56,
<> 144:ef7eb2e8f9f7 28 68, 48, 56, 64, 72,
<> 144:ef7eb2e8f9f7 29 80, 88, 104, 128, 80,
<> 144:ef7eb2e8f9f7 30 96, 112, 128, 144, 160,
<> 144:ef7eb2e8f9f7 31 192, 240, 160, 192, 224,
<> 144:ef7eb2e8f9f7 32 256, 288, 320, 384, 480,
<> 144:ef7eb2e8f9f7 33 320, 384, 448, 512, 576,
<> 144:ef7eb2e8f9f7 34 640, 768, 960, 640, 768,
<> 144:ef7eb2e8f9f7 35 896, 1024, 1152, 1280, 1536,
<> 144:ef7eb2e8f9f7 36 1920, 1280, 1536, 1792, 2048,
<> 144:ef7eb2e8f9f7 37 2304, 2560, 3072, 3840
<> 144:ef7eb2e8f9f7 38 };
<> 144:ef7eb2e8f9f7 39
<> 144:ef7eb2e8f9f7 40
<> 144:ef7eb2e8f9f7 41 void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
<> 144:ef7eb2e8f9f7 42 // determine the I2C to use
<> 144:ef7eb2e8f9f7 43 I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
<> 144:ef7eb2e8f9f7 44 I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
<> 144:ef7eb2e8f9f7 45 obj->i2c = (I2C_Type*)pinmap_merge(i2c_sda, i2c_scl);
<> 144:ef7eb2e8f9f7 46 MBED_ASSERT((int)obj->i2c != NC);
<> 144:ef7eb2e8f9f7 47
<> 144:ef7eb2e8f9f7 48 #if defined(TARGET_K20DX256)
<> 144:ef7eb2e8f9f7 49 switch ((int)obj->i2c) {
<> 144:ef7eb2e8f9f7 50 case I2C_0: SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK;
<> 144:ef7eb2e8f9f7 51 case I2C_1: SIM->SCGC4 |= SIM_SCGC4_I2C1_MASK;
<> 144:ef7eb2e8f9f7 52 }
<> 144:ef7eb2e8f9f7 53 #else
<> 144:ef7eb2e8f9f7 54 SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK;
<> 144:ef7eb2e8f9f7 55 #endif
<> 144:ef7eb2e8f9f7 56
<> 144:ef7eb2e8f9f7 57 // set default frequency at 100k
<> 144:ef7eb2e8f9f7 58 i2c_frequency(obj, 100000);
<> 144:ef7eb2e8f9f7 59
<> 144:ef7eb2e8f9f7 60 // enable I2C interface
<> 144:ef7eb2e8f9f7 61 obj->i2c->C1 |= 0x80;
<> 144:ef7eb2e8f9f7 62
<> 144:ef7eb2e8f9f7 63 pinmap_pinout(sda, PinMap_I2C_SDA);
<> 144:ef7eb2e8f9f7 64 pinmap_pinout(scl, PinMap_I2C_SCL);
<> 144:ef7eb2e8f9f7 65 /* enable open drain for I2C pins, only port b available */
<> 144:ef7eb2e8f9f7 66 uint32_t pin_n = (uint32_t)(sda & 0x7C) >> 2;
<> 144:ef7eb2e8f9f7 67 PORTB->PCR[pin_n] |= PORT_PCR_ODE_MASK;
<> 144:ef7eb2e8f9f7 68 pin_n = (uint32_t)(scl & 0x7C) >> 2;
<> 144:ef7eb2e8f9f7 69 PORTB->PCR[pin_n] |= PORT_PCR_ODE_MASK;
<> 144:ef7eb2e8f9f7 70 }
<> 144:ef7eb2e8f9f7 71
<> 144:ef7eb2e8f9f7 72 int i2c_start(i2c_t *obj) {
<> 144:ef7eb2e8f9f7 73 // if we are in the middle of a transaction
<> 144:ef7eb2e8f9f7 74 // activate the repeat_start flag
<> 144:ef7eb2e8f9f7 75 if (obj->i2c->S & I2C_S_BUSY_MASK) {
<> 144:ef7eb2e8f9f7 76 obj->i2c->C1 |= 0x04;
<> 144:ef7eb2e8f9f7 77 } else {
<> 144:ef7eb2e8f9f7 78 obj->i2c->C1 |= I2C_C1_MST_MASK;
<> 144:ef7eb2e8f9f7 79 obj->i2c->C1 |= I2C_C1_TX_MASK;
<> 144:ef7eb2e8f9f7 80 }
<> 144:ef7eb2e8f9f7 81 return 0;
<> 144:ef7eb2e8f9f7 82 }
<> 144:ef7eb2e8f9f7 83
<> 144:ef7eb2e8f9f7 84 int i2c_stop(i2c_t *obj) {
<> 144:ef7eb2e8f9f7 85 volatile uint32_t n = 0;
<> 144:ef7eb2e8f9f7 86 obj->i2c->C1 &= ~I2C_C1_MST_MASK;
<> 144:ef7eb2e8f9f7 87 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
<> 144:ef7eb2e8f9f7 88 while(obj->i2c->S & I2C_S_BUSY_MASK);
<> 144:ef7eb2e8f9f7 89 return 0;
<> 144:ef7eb2e8f9f7 90 }
<> 144:ef7eb2e8f9f7 91
<> 144:ef7eb2e8f9f7 92 static int timeout_status_poll(i2c_t *obj, uint32_t mask) {
<> 144:ef7eb2e8f9f7 93 uint32_t i, timeout = 100000;
<> 144:ef7eb2e8f9f7 94
<> 144:ef7eb2e8f9f7 95 for (i = 0; i < timeout; i++) {
<> 144:ef7eb2e8f9f7 96 if (obj->i2c->S & mask)
<> 144:ef7eb2e8f9f7 97 return 0;
<> 144:ef7eb2e8f9f7 98 }
<> 144:ef7eb2e8f9f7 99
<> 144:ef7eb2e8f9f7 100 return 1;
<> 144:ef7eb2e8f9f7 101 }
<> 144:ef7eb2e8f9f7 102
<> 144:ef7eb2e8f9f7 103 // this function waits the end of a tx transfer and return the status of the transaction:
<> 144:ef7eb2e8f9f7 104 // 0: OK ack received
<> 144:ef7eb2e8f9f7 105 // 1: OK ack not received
<> 144:ef7eb2e8f9f7 106 // 2: failure
<> 144:ef7eb2e8f9f7 107 static int i2c_wait_end_tx_transfer(i2c_t *obj) {
<> 144:ef7eb2e8f9f7 108
<> 144:ef7eb2e8f9f7 109 // wait for the interrupt flag
<> 144:ef7eb2e8f9f7 110 if (timeout_status_poll(obj, I2C_S_IICIF_MASK)) {
<> 144:ef7eb2e8f9f7 111 return 2;
<> 144:ef7eb2e8f9f7 112 }
<> 144:ef7eb2e8f9f7 113
<> 144:ef7eb2e8f9f7 114 obj->i2c->S |= I2C_S_IICIF_MASK;
<> 144:ef7eb2e8f9f7 115
<> 144:ef7eb2e8f9f7 116 // wait transfer complete
<> 144:ef7eb2e8f9f7 117 if (timeout_status_poll(obj, I2C_S_TCF_MASK)) {
<> 144:ef7eb2e8f9f7 118 return 2;
<> 144:ef7eb2e8f9f7 119 }
<> 144:ef7eb2e8f9f7 120
<> 144:ef7eb2e8f9f7 121 // check if we received the ACK or not
<> 144:ef7eb2e8f9f7 122 return obj->i2c->S & I2C_S_RXAK_MASK ? 1 : 0;
<> 144:ef7eb2e8f9f7 123 }
<> 144:ef7eb2e8f9f7 124
<> 144:ef7eb2e8f9f7 125 // this function waits the end of a rx transfer and return the status of the transaction:
<> 144:ef7eb2e8f9f7 126 // 0: OK
<> 144:ef7eb2e8f9f7 127 // 1: failure
<> 144:ef7eb2e8f9f7 128 static int i2c_wait_end_rx_transfer(i2c_t *obj) {
<> 144:ef7eb2e8f9f7 129 // wait for the end of the rx transfer
<> 144:ef7eb2e8f9f7 130 if (timeout_status_poll(obj, I2C_S_IICIF_MASK)) {
<> 144:ef7eb2e8f9f7 131 return 1;
<> 144:ef7eb2e8f9f7 132 }
<> 144:ef7eb2e8f9f7 133
<> 144:ef7eb2e8f9f7 134 obj->i2c->S |= I2C_S_IICIF_MASK;
<> 144:ef7eb2e8f9f7 135
<> 144:ef7eb2e8f9f7 136 return 0;
<> 144:ef7eb2e8f9f7 137 }
<> 144:ef7eb2e8f9f7 138
<> 144:ef7eb2e8f9f7 139 static void i2c_send_nack(i2c_t *obj) {
<> 144:ef7eb2e8f9f7 140 obj->i2c->C1 |= I2C_C1_TXAK_MASK; // NACK
<> 144:ef7eb2e8f9f7 141 }
<> 144:ef7eb2e8f9f7 142
<> 144:ef7eb2e8f9f7 143 static void i2c_send_ack(i2c_t *obj) {
<> 144:ef7eb2e8f9f7 144 obj->i2c->C1 &= ~I2C_C1_TXAK_MASK; // ACK
<> 144:ef7eb2e8f9f7 145 }
<> 144:ef7eb2e8f9f7 146
<> 144:ef7eb2e8f9f7 147 static int i2c_do_write(i2c_t *obj, int value) {
<> 144:ef7eb2e8f9f7 148 // write the data
<> 144:ef7eb2e8f9f7 149 obj->i2c->D = value;
<> 144:ef7eb2e8f9f7 150
<> 144:ef7eb2e8f9f7 151 // init and wait the end of the transfer
<> 144:ef7eb2e8f9f7 152 return i2c_wait_end_tx_transfer(obj);
<> 144:ef7eb2e8f9f7 153 }
<> 144:ef7eb2e8f9f7 154
<> 144:ef7eb2e8f9f7 155 static int i2c_do_read(i2c_t *obj, char * data, int last) {
<> 144:ef7eb2e8f9f7 156 if (last) {
<> 144:ef7eb2e8f9f7 157 i2c_send_nack(obj);
<> 144:ef7eb2e8f9f7 158 } else {
<> 144:ef7eb2e8f9f7 159 i2c_send_ack(obj);
<> 144:ef7eb2e8f9f7 160 }
<> 144:ef7eb2e8f9f7 161
<> 144:ef7eb2e8f9f7 162 *data = (obj->i2c->D & 0xFF);
<> 144:ef7eb2e8f9f7 163
<> 144:ef7eb2e8f9f7 164 // start rx transfer and wait the end of the transfer
<> 144:ef7eb2e8f9f7 165 return i2c_wait_end_rx_transfer(obj);
<> 144:ef7eb2e8f9f7 166 }
<> 144:ef7eb2e8f9f7 167
<> 144:ef7eb2e8f9f7 168 void i2c_frequency(i2c_t *obj, int hz) {
<> 144:ef7eb2e8f9f7 169 uint8_t icr = 0;
<> 144:ef7eb2e8f9f7 170 uint8_t mult = 0;
<> 144:ef7eb2e8f9f7 171 uint32_t error = 0;
<> 144:ef7eb2e8f9f7 172 uint32_t p_error = 0xffffffff;
<> 144:ef7eb2e8f9f7 173 uint32_t ref = 0;
<> 144:ef7eb2e8f9f7 174 uint8_t i, j;
<> 144:ef7eb2e8f9f7 175 // bus clk
<> 144:ef7eb2e8f9f7 176 uint32_t PCLK = bus_frequency();
<> 144:ef7eb2e8f9f7 177 uint32_t pulse = PCLK / (hz * 2);
<> 144:ef7eb2e8f9f7 178
<> 144:ef7eb2e8f9f7 179 // we look for the values that minimize the error
<> 144:ef7eb2e8f9f7 180
<> 144:ef7eb2e8f9f7 181 // test all the MULT values
<> 144:ef7eb2e8f9f7 182 for (i = 1; i < 5; i*=2) {
<> 144:ef7eb2e8f9f7 183 for (j = 0; j < 0x40; j++) {
<> 144:ef7eb2e8f9f7 184 ref = PCLK / (i*ICR[j]);
<> 144:ef7eb2e8f9f7 185 if (ref > (uint32_t)hz)
<> 144:ef7eb2e8f9f7 186 continue;
<> 144:ef7eb2e8f9f7 187 error = hz - ref;
<> 144:ef7eb2e8f9f7 188 if (error < p_error) {
<> 144:ef7eb2e8f9f7 189 icr = j;
<> 144:ef7eb2e8f9f7 190 mult = i/2;
<> 144:ef7eb2e8f9f7 191 p_error = error;
<> 144:ef7eb2e8f9f7 192 }
<> 144:ef7eb2e8f9f7 193 }
<> 144:ef7eb2e8f9f7 194 }
<> 144:ef7eb2e8f9f7 195 pulse = icr | (mult << 6);
<> 144:ef7eb2e8f9f7 196
<> 144:ef7eb2e8f9f7 197 // I2C Rate
<> 144:ef7eb2e8f9f7 198 obj->i2c->F = pulse;
<> 144:ef7eb2e8f9f7 199 }
<> 144:ef7eb2e8f9f7 200
<> 144:ef7eb2e8f9f7 201 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
<> 144:ef7eb2e8f9f7 202 int count;
<> 144:ef7eb2e8f9f7 203 char dummy_read, *ptr;
<> 144:ef7eb2e8f9f7 204
<> 144:ef7eb2e8f9f7 205 if (i2c_start(obj)) {
<> 144:ef7eb2e8f9f7 206 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 207 return I2C_ERROR_BUS_BUSY;
<> 144:ef7eb2e8f9f7 208 }
<> 144:ef7eb2e8f9f7 209
<> 144:ef7eb2e8f9f7 210 if (i2c_do_write(obj, (address | 0x01))) {
<> 144:ef7eb2e8f9f7 211 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 212 return I2C_ERROR_NO_SLAVE;
<> 144:ef7eb2e8f9f7 213 }
<> 144:ef7eb2e8f9f7 214
<> 144:ef7eb2e8f9f7 215 // set rx mode
<> 144:ef7eb2e8f9f7 216 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
<> 144:ef7eb2e8f9f7 217
<> 144:ef7eb2e8f9f7 218 // Read in bytes
<> 144:ef7eb2e8f9f7 219 for (count = 0; count < (length); count++) {
<> 144:ef7eb2e8f9f7 220 ptr = (count == 0) ? &dummy_read : &data[count - 1];
<> 144:ef7eb2e8f9f7 221 uint8_t stop_ = (count == (length - 1)) ? 1 : 0;
<> 144:ef7eb2e8f9f7 222 if (i2c_do_read(obj, ptr, stop_)) {
<> 144:ef7eb2e8f9f7 223 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 224 return count;
<> 144:ef7eb2e8f9f7 225 }
<> 144:ef7eb2e8f9f7 226 }
<> 144:ef7eb2e8f9f7 227
<> 144:ef7eb2e8f9f7 228 // If not repeated start, send stop.
<> 144:ef7eb2e8f9f7 229 if (stop)
<> 144:ef7eb2e8f9f7 230 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 231
<> 144:ef7eb2e8f9f7 232 // last read
<> 144:ef7eb2e8f9f7 233 data[count-1] = obj->i2c->D;
<> 144:ef7eb2e8f9f7 234
<> 144:ef7eb2e8f9f7 235 return length;
<> 144:ef7eb2e8f9f7 236 }
<> 144:ef7eb2e8f9f7 237 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
<> 144:ef7eb2e8f9f7 238 int i;
<> 144:ef7eb2e8f9f7 239
<> 144:ef7eb2e8f9f7 240 if (i2c_start(obj)) {
<> 144:ef7eb2e8f9f7 241 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 242 return I2C_ERROR_BUS_BUSY;
<> 144:ef7eb2e8f9f7 243 }
<> 144:ef7eb2e8f9f7 244
<> 144:ef7eb2e8f9f7 245 if (i2c_do_write(obj, (address & 0xFE))) {
<> 144:ef7eb2e8f9f7 246 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 247 return I2C_ERROR_NO_SLAVE;
<> 144:ef7eb2e8f9f7 248 }
<> 144:ef7eb2e8f9f7 249
<> 144:ef7eb2e8f9f7 250 for (i = 0; i < length; i++) {
<> 144:ef7eb2e8f9f7 251 if(i2c_do_write(obj, data[i])) {
<> 144:ef7eb2e8f9f7 252 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 253 return i;
<> 144:ef7eb2e8f9f7 254 }
<> 144:ef7eb2e8f9f7 255 }
<> 144:ef7eb2e8f9f7 256
<> 144:ef7eb2e8f9f7 257 if (stop)
<> 144:ef7eb2e8f9f7 258 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 259
<> 144:ef7eb2e8f9f7 260 return length;
<> 144:ef7eb2e8f9f7 261 }
<> 144:ef7eb2e8f9f7 262
<> 144:ef7eb2e8f9f7 263 void i2c_reset(i2c_t *obj) {
<> 144:ef7eb2e8f9f7 264 i2c_stop(obj);
<> 144:ef7eb2e8f9f7 265 }
<> 144:ef7eb2e8f9f7 266
<> 144:ef7eb2e8f9f7 267 int i2c_byte_read(i2c_t *obj, int last) {
<> 144:ef7eb2e8f9f7 268 char data;
<> 144:ef7eb2e8f9f7 269
<> 144:ef7eb2e8f9f7 270 // set rx mode
<> 144:ef7eb2e8f9f7 271 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
<> 144:ef7eb2e8f9f7 272
<> 144:ef7eb2e8f9f7 273 // Setup read
<> 144:ef7eb2e8f9f7 274 i2c_do_read(obj, &data, last);
<> 144:ef7eb2e8f9f7 275
<> 144:ef7eb2e8f9f7 276 // set tx mode
<> 144:ef7eb2e8f9f7 277 obj->i2c->C1 |= I2C_C1_TX_MASK;
<> 144:ef7eb2e8f9f7 278 return obj->i2c->D;
<> 144:ef7eb2e8f9f7 279 }
<> 144:ef7eb2e8f9f7 280
<> 144:ef7eb2e8f9f7 281 int i2c_byte_write(i2c_t *obj, int data) {
<> 144:ef7eb2e8f9f7 282 // set tx mode
<> 144:ef7eb2e8f9f7 283 obj->i2c->C1 |= I2C_C1_TX_MASK;
<> 144:ef7eb2e8f9f7 284
<> 144:ef7eb2e8f9f7 285 return !i2c_do_write(obj, (data & 0xFF));
<> 144:ef7eb2e8f9f7 286 }
<> 144:ef7eb2e8f9f7 287
<> 144:ef7eb2e8f9f7 288
<> 144:ef7eb2e8f9f7 289 #if DEVICE_I2CSLAVE
<> 144:ef7eb2e8f9f7 290 void i2c_slave_mode(i2c_t *obj, int enable_slave) {
<> 144:ef7eb2e8f9f7 291 if (enable_slave) {
<> 144:ef7eb2e8f9f7 292 // set slave mode
<> 144:ef7eb2e8f9f7 293 obj->i2c->C1 &= ~I2C_C1_MST_MASK;
<> 144:ef7eb2e8f9f7 294 obj->i2c->C1 |= I2C_C1_IICIE_MASK;
<> 144:ef7eb2e8f9f7 295 } else {
<> 144:ef7eb2e8f9f7 296 // set master mode
<> 144:ef7eb2e8f9f7 297 obj->i2c->C1 |= I2C_C1_MST_MASK;
<> 144:ef7eb2e8f9f7 298 }
<> 144:ef7eb2e8f9f7 299 }
<> 144:ef7eb2e8f9f7 300
<> 144:ef7eb2e8f9f7 301 int i2c_slave_receive(i2c_t *obj) {
<> 144:ef7eb2e8f9f7 302 switch(obj->i2c->S) {
<> 144:ef7eb2e8f9f7 303 // read addressed
<> 144:ef7eb2e8f9f7 304 case 0xE6:
<> 144:ef7eb2e8f9f7 305 return 1;
<> 144:ef7eb2e8f9f7 306 // write addressed
<> 144:ef7eb2e8f9f7 307 case 0xE2:
<> 144:ef7eb2e8f9f7 308 return 3;
<> 144:ef7eb2e8f9f7 309 default:
<> 144:ef7eb2e8f9f7 310 return 0;
<> 144:ef7eb2e8f9f7 311 }
<> 144:ef7eb2e8f9f7 312 }
<> 144:ef7eb2e8f9f7 313
<> 144:ef7eb2e8f9f7 314 int i2c_slave_read(i2c_t *obj, char *data, int length) {
<> 144:ef7eb2e8f9f7 315 uint8_t dummy_read;
<> 144:ef7eb2e8f9f7 316 uint8_t * ptr;
<> 144:ef7eb2e8f9f7 317 int count;
<> 144:ef7eb2e8f9f7 318
<> 144:ef7eb2e8f9f7 319 // set rx mode
<> 144:ef7eb2e8f9f7 320 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
<> 144:ef7eb2e8f9f7 321
<> 144:ef7eb2e8f9f7 322 // first dummy read
<> 144:ef7eb2e8f9f7 323 dummy_read = obj->i2c->D;
<> 144:ef7eb2e8f9f7 324 if (i2c_wait_end_rx_transfer(obj))
<> 144:ef7eb2e8f9f7 325 return 0;
<> 144:ef7eb2e8f9f7 326
<> 144:ef7eb2e8f9f7 327 // read address
<> 144:ef7eb2e8f9f7 328 dummy_read = obj->i2c->D;
<> 144:ef7eb2e8f9f7 329 if (i2c_wait_end_rx_transfer(obj))
<> 144:ef7eb2e8f9f7 330 return 0;
<> 144:ef7eb2e8f9f7 331
<> 144:ef7eb2e8f9f7 332 // read (length - 1) bytes
<> 144:ef7eb2e8f9f7 333 for (count = 0; count < (length - 1); count++) {
<> 144:ef7eb2e8f9f7 334 data[count] = obj->i2c->D;
<> 144:ef7eb2e8f9f7 335 if (i2c_wait_end_rx_transfer(obj))
<> 144:ef7eb2e8f9f7 336 return count;
<> 144:ef7eb2e8f9f7 337 }
<> 144:ef7eb2e8f9f7 338
<> 144:ef7eb2e8f9f7 339 // read last byte
<> 144:ef7eb2e8f9f7 340 ptr = (length == 0) ? &dummy_read : (uint8_t *)&data[count];
<> 144:ef7eb2e8f9f7 341 *ptr = obj->i2c->D;
<> 144:ef7eb2e8f9f7 342
<> 144:ef7eb2e8f9f7 343 return (length) ? (count + 1) : 0;
<> 144:ef7eb2e8f9f7 344 }
<> 144:ef7eb2e8f9f7 345
<> 144:ef7eb2e8f9f7 346 int i2c_slave_write(i2c_t *obj, const char *data, int length) {
<> 144:ef7eb2e8f9f7 347 int i, count = 0;
<> 144:ef7eb2e8f9f7 348
<> 144:ef7eb2e8f9f7 349 // set tx mode
<> 144:ef7eb2e8f9f7 350 obj->i2c->C1 |= I2C_C1_TX_MASK;
<> 144:ef7eb2e8f9f7 351
<> 144:ef7eb2e8f9f7 352 for (i = 0; i < length; i++) {
<> 144:ef7eb2e8f9f7 353 if (i2c_do_write(obj, data[count++]) == 2)
<> 144:ef7eb2e8f9f7 354 return i;
<> 144:ef7eb2e8f9f7 355 }
<> 144:ef7eb2e8f9f7 356
<> 144:ef7eb2e8f9f7 357 // set rx mode
<> 144:ef7eb2e8f9f7 358 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
<> 144:ef7eb2e8f9f7 359
<> 144:ef7eb2e8f9f7 360 // dummy rx transfer needed
<> 144:ef7eb2e8f9f7 361 // otherwise the master cannot generate a stop bit
<> 144:ef7eb2e8f9f7 362 obj->i2c->D;
<> 144:ef7eb2e8f9f7 363 if (i2c_wait_end_rx_transfer(obj) == 2)
<> 144:ef7eb2e8f9f7 364 return count;
<> 144:ef7eb2e8f9f7 365
<> 144:ef7eb2e8f9f7 366 return count;
<> 144:ef7eb2e8f9f7 367 }
<> 144:ef7eb2e8f9f7 368
<> 144:ef7eb2e8f9f7 369 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
<> 144:ef7eb2e8f9f7 370 obj->i2c->A1 = address & 0xfe;
<> 144:ef7eb2e8f9f7 371 }
<> 144:ef7eb2e8f9f7 372 #endif