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
targets/TARGET_TOSHIBA/TARGET_TMPM066/i2c_api.c@177:619788de047e, 2017-11-07 (annotated)
- Committer:
- maxxir
- Date:
- Tue Nov 07 16:46:29 2017 +0000
- Revision:
- 177:619788de047e
- Parent:
- 172:7d866c31b3c5
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?
User | Revision | Line number | New contents of line |
---|---|---|---|
AnnaBridge | 172:7d866c31b3c5 | 1 | /* mbed Microcontroller Library |
AnnaBridge | 172:7d866c31b3c5 | 2 | * (C)Copyright TOSHIBA ELECTRONIC DEVICES & STORAGE CORPORATION 2017 All rights reserved |
AnnaBridge | 172:7d866c31b3c5 | 3 | * |
AnnaBridge | 172:7d866c31b3c5 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
AnnaBridge | 172:7d866c31b3c5 | 5 | * you may not use this file except in compliance with the License. |
AnnaBridge | 172:7d866c31b3c5 | 6 | * You may obtain a copy of the License at |
AnnaBridge | 172:7d866c31b3c5 | 7 | * |
AnnaBridge | 172:7d866c31b3c5 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
AnnaBridge | 172:7d866c31b3c5 | 9 | * |
AnnaBridge | 172:7d866c31b3c5 | 10 | * Unless required by applicable law or agreed to in writing, software |
AnnaBridge | 172:7d866c31b3c5 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
AnnaBridge | 172:7d866c31b3c5 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
AnnaBridge | 172:7d866c31b3c5 | 13 | * See the License for the specific language governing permissions and |
AnnaBridge | 172:7d866c31b3c5 | 14 | * limitations under the License. |
AnnaBridge | 172:7d866c31b3c5 | 15 | */ |
AnnaBridge | 172:7d866c31b3c5 | 16 | #include "i2c_api.h" |
AnnaBridge | 172:7d866c31b3c5 | 17 | #include "mbed_error.h" |
AnnaBridge | 172:7d866c31b3c5 | 18 | #include "PeripheralNames.h" |
AnnaBridge | 172:7d866c31b3c5 | 19 | #include "pinmap.h" |
AnnaBridge | 172:7d866c31b3c5 | 20 | |
AnnaBridge | 172:7d866c31b3c5 | 21 | #define I2C_NACK (0) |
AnnaBridge | 172:7d866c31b3c5 | 22 | #define I2C_ACK (1) |
AnnaBridge | 172:7d866c31b3c5 | 23 | #define I2C_NO_DATA (0) |
AnnaBridge | 172:7d866c31b3c5 | 24 | #define I2C_READ_ADDRESSED (1) |
AnnaBridge | 172:7d866c31b3c5 | 25 | #define I2C_WRITE_GENERAL (2) |
AnnaBridge | 172:7d866c31b3c5 | 26 | #define I2C_WRITE_ADDRESSED (3) |
AnnaBridge | 172:7d866c31b3c5 | 27 | #define SELF_ADDR (0xE0) |
AnnaBridge | 172:7d866c31b3c5 | 28 | #define I2C_TIMEOUT (100000) |
AnnaBridge | 172:7d866c31b3c5 | 29 | |
AnnaBridge | 172:7d866c31b3c5 | 30 | static const PinMap PinMap_I2C_SDA[] = { |
AnnaBridge | 172:7d866c31b3c5 | 31 | {PC1, I2C_0, PIN_DATA(1, 2)}, |
AnnaBridge | 172:7d866c31b3c5 | 32 | {PG1, I2C_1, PIN_DATA(1, 2)}, |
AnnaBridge | 172:7d866c31b3c5 | 33 | {NC, NC, 0} |
AnnaBridge | 172:7d866c31b3c5 | 34 | }; |
AnnaBridge | 172:7d866c31b3c5 | 35 | |
AnnaBridge | 172:7d866c31b3c5 | 36 | static const PinMap PinMap_I2C_SCL[] = { |
AnnaBridge | 172:7d866c31b3c5 | 37 | {PC0, I2C_0, PIN_DATA(1, 2)}, |
AnnaBridge | 172:7d866c31b3c5 | 38 | {PG0, I2C_1, PIN_DATA(1, 2)}, |
AnnaBridge | 172:7d866c31b3c5 | 39 | {NC, NC, 0} |
AnnaBridge | 172:7d866c31b3c5 | 40 | }; |
AnnaBridge | 172:7d866c31b3c5 | 41 | |
AnnaBridge | 172:7d866c31b3c5 | 42 | void I2C_ClearINTOutput(TSB_I2C_TypeDef * I2Cx); |
AnnaBridge | 172:7d866c31b3c5 | 43 | // Clock setting structure definition |
AnnaBridge | 172:7d866c31b3c5 | 44 | typedef struct { |
AnnaBridge | 172:7d866c31b3c5 | 45 | uint32_t sck; |
AnnaBridge | 172:7d866c31b3c5 | 46 | uint32_t prsck; |
AnnaBridge | 172:7d866c31b3c5 | 47 | } I2C_clock_setting_t; |
AnnaBridge | 172:7d866c31b3c5 | 48 | |
AnnaBridge | 172:7d866c31b3c5 | 49 | static const uint32_t I2C_SCK_DIVIDER_TBL[8] = {20, 24, 32, 48, 80, 144, 272, 528}; // SCK Divider value table |
AnnaBridge | 172:7d866c31b3c5 | 50 | static uint32_t start_flag = 0; |
AnnaBridge | 172:7d866c31b3c5 | 51 | I2C_clock_setting_t clk; |
AnnaBridge | 172:7d866c31b3c5 | 52 | I2C_State status; |
AnnaBridge | 172:7d866c31b3c5 | 53 | |
AnnaBridge | 172:7d866c31b3c5 | 54 | static int32_t wait_status(i2c_t *obj) |
AnnaBridge | 172:7d866c31b3c5 | 55 | { |
AnnaBridge | 172:7d866c31b3c5 | 56 | volatile int32_t timeout = I2C_TIMEOUT; |
AnnaBridge | 172:7d866c31b3c5 | 57 | |
AnnaBridge | 172:7d866c31b3c5 | 58 | while (I2C_GetINTI2CStatus(obj->i2c) == DISABLE) { |
AnnaBridge | 172:7d866c31b3c5 | 59 | if ((timeout--) == 0) { |
AnnaBridge | 172:7d866c31b3c5 | 60 | return (-1); |
AnnaBridge | 172:7d866c31b3c5 | 61 | } |
AnnaBridge | 172:7d866c31b3c5 | 62 | } |
AnnaBridge | 172:7d866c31b3c5 | 63 | return (0); |
AnnaBridge | 172:7d866c31b3c5 | 64 | } |
AnnaBridge | 172:7d866c31b3c5 | 65 | |
AnnaBridge | 172:7d866c31b3c5 | 66 | // Initialize the I2C peripheral. It sets the default parameters for I2C |
AnnaBridge | 172:7d866c31b3c5 | 67 | void i2c_init(i2c_t *obj, PinName sda, PinName scl) |
AnnaBridge | 172:7d866c31b3c5 | 68 | { |
AnnaBridge | 172:7d866c31b3c5 | 69 | MBED_ASSERT(obj != NULL); |
AnnaBridge | 172:7d866c31b3c5 | 70 | I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); |
AnnaBridge | 172:7d866c31b3c5 | 71 | I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); |
AnnaBridge | 172:7d866c31b3c5 | 72 | I2CName i2c_name = (I2CName)pinmap_merge(i2c_sda, i2c_scl); |
AnnaBridge | 172:7d866c31b3c5 | 73 | MBED_ASSERT((int)i2c_name != NC); |
AnnaBridge | 172:7d866c31b3c5 | 74 | |
AnnaBridge | 172:7d866c31b3c5 | 75 | switch (i2c_name) { |
AnnaBridge | 172:7d866c31b3c5 | 76 | case I2C_0: |
AnnaBridge | 172:7d866c31b3c5 | 77 | CG_SetFcPeriphA(CG_FC_PERIPH_I2C0, ENABLE); |
AnnaBridge | 172:7d866c31b3c5 | 78 | obj->i2c = TSB_I2C0; |
AnnaBridge | 172:7d866c31b3c5 | 79 | obj->IRQn = INTI2C0_IRQn; |
AnnaBridge | 172:7d866c31b3c5 | 80 | break; |
AnnaBridge | 172:7d866c31b3c5 | 81 | case I2C_1: |
AnnaBridge | 172:7d866c31b3c5 | 82 | CG_SetFcPeriphB(CG_FC_PERIPH_I2C1, ENABLE); |
AnnaBridge | 172:7d866c31b3c5 | 83 | obj->i2c = TSB_I2C1; |
AnnaBridge | 172:7d866c31b3c5 | 84 | obj->IRQn = INTI2C1_IRQn; |
AnnaBridge | 172:7d866c31b3c5 | 85 | break; |
AnnaBridge | 172:7d866c31b3c5 | 86 | default: |
AnnaBridge | 172:7d866c31b3c5 | 87 | error("I2C is not available"); |
AnnaBridge | 172:7d866c31b3c5 | 88 | break; |
AnnaBridge | 172:7d866c31b3c5 | 89 | } |
AnnaBridge | 172:7d866c31b3c5 | 90 | |
AnnaBridge | 172:7d866c31b3c5 | 91 | pinmap_pinout(sda, PinMap_I2C_SDA); |
AnnaBridge | 172:7d866c31b3c5 | 92 | pin_mode(sda, OpenDrain); |
AnnaBridge | 172:7d866c31b3c5 | 93 | pin_mode(sda, PullUp); |
AnnaBridge | 172:7d866c31b3c5 | 94 | |
AnnaBridge | 172:7d866c31b3c5 | 95 | pinmap_pinout(scl, PinMap_I2C_SCL); |
AnnaBridge | 172:7d866c31b3c5 | 96 | pin_mode(scl, OpenDrain); |
AnnaBridge | 172:7d866c31b3c5 | 97 | pin_mode(scl, PullUp); |
AnnaBridge | 172:7d866c31b3c5 | 98 | |
AnnaBridge | 172:7d866c31b3c5 | 99 | NVIC_DisableIRQ(obj->IRQn); |
AnnaBridge | 172:7d866c31b3c5 | 100 | |
AnnaBridge | 172:7d866c31b3c5 | 101 | i2c_reset(obj); |
AnnaBridge | 172:7d866c31b3c5 | 102 | i2c_frequency(obj, 100000); |
AnnaBridge | 172:7d866c31b3c5 | 103 | } |
AnnaBridge | 172:7d866c31b3c5 | 104 | |
AnnaBridge | 172:7d866c31b3c5 | 105 | // Configure the I2C frequency |
AnnaBridge | 172:7d866c31b3c5 | 106 | void i2c_frequency(i2c_t *obj, int hz) |
AnnaBridge | 172:7d866c31b3c5 | 107 | { |
AnnaBridge | 172:7d866c31b3c5 | 108 | uint64_t sck, tmp_sck; |
AnnaBridge | 172:7d866c31b3c5 | 109 | uint64_t prsck, tmp_prsck; |
AnnaBridge | 172:7d866c31b3c5 | 110 | uint64_t fscl, tmp_fscl; |
AnnaBridge | 172:7d866c31b3c5 | 111 | uint64_t fx; |
AnnaBridge | 172:7d866c31b3c5 | 112 | |
AnnaBridge | 172:7d866c31b3c5 | 113 | SystemCoreClockUpdate(); |
AnnaBridge | 172:7d866c31b3c5 | 114 | |
AnnaBridge | 172:7d866c31b3c5 | 115 | if (hz <= 1000000) { |
AnnaBridge | 172:7d866c31b3c5 | 116 | sck = tmp_sck = 0; |
AnnaBridge | 172:7d866c31b3c5 | 117 | prsck = tmp_prsck = 1; |
AnnaBridge | 172:7d866c31b3c5 | 118 | fscl = tmp_fscl = 0; |
AnnaBridge | 172:7d866c31b3c5 | 119 | for (prsck = 1; prsck <= 32; prsck++) { |
AnnaBridge | 172:7d866c31b3c5 | 120 | fx = ((uint64_t)SystemCoreClock / prsck); |
AnnaBridge | 172:7d866c31b3c5 | 121 | if ((fx < 40000000U) && (fx > 6666666U)) { |
AnnaBridge | 172:7d866c31b3c5 | 122 | for (sck = 0; sck <= 7; sck++) { |
AnnaBridge | 172:7d866c31b3c5 | 123 | fscl = (fx / (uint64_t)I2C_SCK_DIVIDER_TBL[sck]); |
AnnaBridge | 172:7d866c31b3c5 | 124 | if ((fscl <= (uint64_t)hz) && (fscl > tmp_fscl)) { |
AnnaBridge | 172:7d866c31b3c5 | 125 | tmp_fscl = fscl; |
AnnaBridge | 172:7d866c31b3c5 | 126 | tmp_sck = sck; |
AnnaBridge | 172:7d866c31b3c5 | 127 | tmp_prsck = (prsck < 32)? prsck: 0; |
AnnaBridge | 172:7d866c31b3c5 | 128 | } |
AnnaBridge | 172:7d866c31b3c5 | 129 | } |
AnnaBridge | 172:7d866c31b3c5 | 130 | } |
AnnaBridge | 172:7d866c31b3c5 | 131 | } |
AnnaBridge | 172:7d866c31b3c5 | 132 | clk.sck = (uint32_t)tmp_sck; |
AnnaBridge | 172:7d866c31b3c5 | 133 | clk.prsck = (tmp_prsck < 32) ? (uint32_t)(tmp_prsck) : 0; |
AnnaBridge | 172:7d866c31b3c5 | 134 | } |
AnnaBridge | 172:7d866c31b3c5 | 135 | obj->myi2c.I2CSelfAddr = SELF_ADDR; |
AnnaBridge | 172:7d866c31b3c5 | 136 | obj->myi2c.I2CDataLen = I2C_DATA_LEN_8; |
AnnaBridge | 172:7d866c31b3c5 | 137 | obj->myi2c.I2CACKState = ENABLE; |
AnnaBridge | 172:7d866c31b3c5 | 138 | obj->myi2c.I2CClkDiv = clk.sck; |
AnnaBridge | 172:7d866c31b3c5 | 139 | obj->myi2c.PrescalerClkDiv = clk.prsck; |
AnnaBridge | 172:7d866c31b3c5 | 140 | |
AnnaBridge | 172:7d866c31b3c5 | 141 | I2C_Init(obj->i2c, &obj->myi2c); |
AnnaBridge | 172:7d866c31b3c5 | 142 | NVIC_DisableIRQ(obj->IRQn); |
AnnaBridge | 172:7d866c31b3c5 | 143 | } |
AnnaBridge | 172:7d866c31b3c5 | 144 | |
AnnaBridge | 172:7d866c31b3c5 | 145 | int i2c_start(i2c_t *obj) |
AnnaBridge | 172:7d866c31b3c5 | 146 | { |
AnnaBridge | 172:7d866c31b3c5 | 147 | start_flag = 1; |
AnnaBridge | 172:7d866c31b3c5 | 148 | return 0; |
AnnaBridge | 172:7d866c31b3c5 | 149 | } |
AnnaBridge | 172:7d866c31b3c5 | 150 | |
AnnaBridge | 172:7d866c31b3c5 | 151 | int i2c_stop(i2c_t *obj) |
AnnaBridge | 172:7d866c31b3c5 | 152 | { |
AnnaBridge | 172:7d866c31b3c5 | 153 | I2C_GenerateStop(obj->i2c); |
AnnaBridge | 172:7d866c31b3c5 | 154 | return 0; |
AnnaBridge | 172:7d866c31b3c5 | 155 | } |
AnnaBridge | 172:7d866c31b3c5 | 156 | |
AnnaBridge | 172:7d866c31b3c5 | 157 | void i2c_reset(i2c_t *obj) |
AnnaBridge | 172:7d866c31b3c5 | 158 | { |
AnnaBridge | 172:7d866c31b3c5 | 159 | I2C_SWReset(obj->i2c); |
AnnaBridge | 172:7d866c31b3c5 | 160 | } |
AnnaBridge | 172:7d866c31b3c5 | 161 | |
AnnaBridge | 172:7d866c31b3c5 | 162 | int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) |
AnnaBridge | 172:7d866c31b3c5 | 163 | { |
AnnaBridge | 172:7d866c31b3c5 | 164 | int32_t result = 0; |
AnnaBridge | 172:7d866c31b3c5 | 165 | int32_t count = 0; |
AnnaBridge | 172:7d866c31b3c5 | 166 | |
AnnaBridge | 172:7d866c31b3c5 | 167 | if (length > 0) { |
AnnaBridge | 172:7d866c31b3c5 | 168 | start_flag = 1; // Start Condition |
AnnaBridge | 172:7d866c31b3c5 | 169 | if (i2c_byte_write(obj, (int32_t)((uint32_t)address | 1U)) == I2C_ACK) { |
AnnaBridge | 172:7d866c31b3c5 | 170 | while (count < length) { |
AnnaBridge | 172:7d866c31b3c5 | 171 | int32_t pdata = i2c_byte_read(obj, ((count < (length - 1)) ? 0 : 1)); |
AnnaBridge | 172:7d866c31b3c5 | 172 | if (pdata < 0) { |
AnnaBridge | 172:7d866c31b3c5 | 173 | break; |
AnnaBridge | 172:7d866c31b3c5 | 174 | } |
AnnaBridge | 172:7d866c31b3c5 | 175 | data[count++] = (uint8_t)pdata; |
AnnaBridge | 172:7d866c31b3c5 | 176 | } |
AnnaBridge | 172:7d866c31b3c5 | 177 | result = count; |
AnnaBridge | 172:7d866c31b3c5 | 178 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 179 | stop = 1; |
AnnaBridge | 172:7d866c31b3c5 | 180 | result = I2C_ERROR_NO_SLAVE; |
AnnaBridge | 172:7d866c31b3c5 | 181 | } |
AnnaBridge | 172:7d866c31b3c5 | 182 | |
AnnaBridge | 172:7d866c31b3c5 | 183 | if (stop) { // Stop Condition |
AnnaBridge | 172:7d866c31b3c5 | 184 | i2c_stop(obj); |
AnnaBridge | 172:7d866c31b3c5 | 185 | } |
AnnaBridge | 172:7d866c31b3c5 | 186 | } |
AnnaBridge | 172:7d866c31b3c5 | 187 | return (result); |
AnnaBridge | 172:7d866c31b3c5 | 188 | } |
AnnaBridge | 172:7d866c31b3c5 | 189 | |
AnnaBridge | 172:7d866c31b3c5 | 190 | int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) // Blocking sending data |
AnnaBridge | 172:7d866c31b3c5 | 191 | { |
AnnaBridge | 172:7d866c31b3c5 | 192 | int32_t result = 0; |
AnnaBridge | 172:7d866c31b3c5 | 193 | int32_t count = 0; |
AnnaBridge | 172:7d866c31b3c5 | 194 | |
AnnaBridge | 172:7d866c31b3c5 | 195 | start_flag = 1; // Start Condition |
AnnaBridge | 172:7d866c31b3c5 | 196 | if (i2c_byte_write(obj, address) == I2C_ACK) { |
AnnaBridge | 172:7d866c31b3c5 | 197 | while (count < length) { |
AnnaBridge | 172:7d866c31b3c5 | 198 | if (i2c_byte_write(obj, (int32_t)data[count++]) < I2C_ACK) { |
AnnaBridge | 172:7d866c31b3c5 | 199 | break; |
AnnaBridge | 172:7d866c31b3c5 | 200 | } |
AnnaBridge | 172:7d866c31b3c5 | 201 | } |
AnnaBridge | 172:7d866c31b3c5 | 202 | result = count; |
AnnaBridge | 172:7d866c31b3c5 | 203 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 204 | stop = 1; |
AnnaBridge | 172:7d866c31b3c5 | 205 | result = I2C_ERROR_NO_SLAVE; |
AnnaBridge | 172:7d866c31b3c5 | 206 | } |
AnnaBridge | 172:7d866c31b3c5 | 207 | |
AnnaBridge | 172:7d866c31b3c5 | 208 | if (stop) { // Stop Condition |
AnnaBridge | 172:7d866c31b3c5 | 209 | i2c_stop(obj); |
AnnaBridge | 172:7d866c31b3c5 | 210 | } |
AnnaBridge | 172:7d866c31b3c5 | 211 | return (result); |
AnnaBridge | 172:7d866c31b3c5 | 212 | } |
AnnaBridge | 172:7d866c31b3c5 | 213 | |
AnnaBridge | 172:7d866c31b3c5 | 214 | int i2c_byte_read(i2c_t *obj, int last) |
AnnaBridge | 172:7d866c31b3c5 | 215 | { |
AnnaBridge | 172:7d866c31b3c5 | 216 | int32_t result; |
AnnaBridge | 172:7d866c31b3c5 | 217 | |
AnnaBridge | 172:7d866c31b3c5 | 218 | I2C_ClearINTOutput(obj->i2c); |
AnnaBridge | 172:7d866c31b3c5 | 219 | |
AnnaBridge | 172:7d866c31b3c5 | 220 | if (last) { |
AnnaBridge | 172:7d866c31b3c5 | 221 | I2C_SelectACKoutput(obj->i2c, ENABLE); |
AnnaBridge | 172:7d866c31b3c5 | 222 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 223 | I2C_SelectACKoutput(obj->i2c, DISABLE); |
AnnaBridge | 172:7d866c31b3c5 | 224 | } |
AnnaBridge | 172:7d866c31b3c5 | 225 | I2C_SetSendData(obj->i2c, 0x00); |
AnnaBridge | 172:7d866c31b3c5 | 226 | |
AnnaBridge | 172:7d866c31b3c5 | 227 | if (wait_status(obj) < 0) { |
AnnaBridge | 172:7d866c31b3c5 | 228 | result = -1; |
AnnaBridge | 172:7d866c31b3c5 | 229 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 230 | result = (int32_t)I2C_GetReceiveData(obj->i2c); |
AnnaBridge | 172:7d866c31b3c5 | 231 | } |
AnnaBridge | 172:7d866c31b3c5 | 232 | return (result); |
AnnaBridge | 172:7d866c31b3c5 | 233 | } |
AnnaBridge | 172:7d866c31b3c5 | 234 | |
AnnaBridge | 172:7d866c31b3c5 | 235 | void I2C_Start_Condition(i2c_t *p_obj, uint32_t data) |
AnnaBridge | 172:7d866c31b3c5 | 236 | { |
AnnaBridge | 172:7d866c31b3c5 | 237 | status = I2C_GetState(p_obj->i2c); |
AnnaBridge | 172:7d866c31b3c5 | 238 | if (status.Bit.BusState) { |
AnnaBridge | 172:7d866c31b3c5 | 239 | I2C_SetRepeatStart(p_obj->i2c, ENABLE); |
AnnaBridge | 172:7d866c31b3c5 | 240 | } |
AnnaBridge | 172:7d866c31b3c5 | 241 | I2C_SetSendData(p_obj->i2c, (uint32_t)data); |
AnnaBridge | 172:7d866c31b3c5 | 242 | I2C_GenerateStart(p_obj->i2c); |
AnnaBridge | 172:7d866c31b3c5 | 243 | } |
AnnaBridge | 172:7d866c31b3c5 | 244 | |
AnnaBridge | 172:7d866c31b3c5 | 245 | int i2c_byte_write(i2c_t *obj, int data) |
AnnaBridge | 172:7d866c31b3c5 | 246 | { |
AnnaBridge | 172:7d866c31b3c5 | 247 | int32_t result; |
AnnaBridge | 172:7d866c31b3c5 | 248 | |
AnnaBridge | 172:7d866c31b3c5 | 249 | I2C_ClearINTOutput(obj->i2c); |
AnnaBridge | 172:7d866c31b3c5 | 250 | |
AnnaBridge | 172:7d866c31b3c5 | 251 | if (start_flag == 1) { |
AnnaBridge | 172:7d866c31b3c5 | 252 | I2C_Start_Condition(obj, (uint32_t)data); |
AnnaBridge | 172:7d866c31b3c5 | 253 | start_flag = 0; |
AnnaBridge | 172:7d866c31b3c5 | 254 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 255 | I2C_SetSendData(obj->i2c, (uint32_t)data); |
AnnaBridge | 172:7d866c31b3c5 | 256 | } |
AnnaBridge | 172:7d866c31b3c5 | 257 | |
AnnaBridge | 172:7d866c31b3c5 | 258 | if (wait_status(obj) < 0) { |
AnnaBridge | 172:7d866c31b3c5 | 259 | return (-1); |
AnnaBridge | 172:7d866c31b3c5 | 260 | } |
AnnaBridge | 172:7d866c31b3c5 | 261 | |
AnnaBridge | 172:7d866c31b3c5 | 262 | status = I2C_GetState(obj->i2c); |
AnnaBridge | 172:7d866c31b3c5 | 263 | if (!status.Bit.LastRxBit) { |
AnnaBridge | 172:7d866c31b3c5 | 264 | result = 1; |
AnnaBridge | 172:7d866c31b3c5 | 265 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 266 | result = 0; |
AnnaBridge | 172:7d866c31b3c5 | 267 | } |
AnnaBridge | 172:7d866c31b3c5 | 268 | return (result); |
AnnaBridge | 172:7d866c31b3c5 | 269 | } |
AnnaBridge | 172:7d866c31b3c5 | 270 | |
AnnaBridge | 172:7d866c31b3c5 | 271 | void i2c_slave_mode(i2c_t *obj, int enable_slave) |
AnnaBridge | 172:7d866c31b3c5 | 272 | { |
AnnaBridge | 172:7d866c31b3c5 | 273 | i2c_reset(obj); |
AnnaBridge | 172:7d866c31b3c5 | 274 | |
AnnaBridge | 172:7d866c31b3c5 | 275 | obj->myi2c.I2CDataLen = I2C_DATA_LEN_8; |
AnnaBridge | 172:7d866c31b3c5 | 276 | obj->myi2c.I2CACKState = ENABLE; |
AnnaBridge | 172:7d866c31b3c5 | 277 | obj->myi2c.I2CClkDiv = clk.sck; |
AnnaBridge | 172:7d866c31b3c5 | 278 | obj->myi2c.PrescalerClkDiv = clk.prsck; |
AnnaBridge | 172:7d866c31b3c5 | 279 | |
AnnaBridge | 172:7d866c31b3c5 | 280 | if (enable_slave) { |
AnnaBridge | 172:7d866c31b3c5 | 281 | obj->myi2c.I2CSelfAddr = obj->address; |
AnnaBridge | 172:7d866c31b3c5 | 282 | I2C_SetINTI2CReq(obj->i2c, ENABLE); |
AnnaBridge | 172:7d866c31b3c5 | 283 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 284 | obj->myi2c.I2CSelfAddr = SELF_ADDR; |
AnnaBridge | 172:7d866c31b3c5 | 285 | NVIC_DisableIRQ(obj->IRQn); |
AnnaBridge | 172:7d866c31b3c5 | 286 | I2C_ClearINTOutput(obj->i2c); |
AnnaBridge | 172:7d866c31b3c5 | 287 | } |
AnnaBridge | 172:7d866c31b3c5 | 288 | I2C_Init(obj->i2c, &obj->myi2c); |
AnnaBridge | 172:7d866c31b3c5 | 289 | } |
AnnaBridge | 172:7d866c31b3c5 | 290 | |
AnnaBridge | 172:7d866c31b3c5 | 291 | int i2c_slave_receive(i2c_t *obj) |
AnnaBridge | 172:7d866c31b3c5 | 292 | { |
AnnaBridge | 172:7d866c31b3c5 | 293 | int32_t result = I2C_NO_DATA; |
AnnaBridge | 172:7d866c31b3c5 | 294 | |
AnnaBridge | 172:7d866c31b3c5 | 295 | if ((I2C_GetINTI2CStatus(obj->i2c)) && (I2C_GetSlaveAddrMatchState(obj->i2c))) { |
AnnaBridge | 172:7d866c31b3c5 | 296 | status = I2C_GetState(obj->i2c); |
AnnaBridge | 172:7d866c31b3c5 | 297 | if (!status.Bit.TRx) { |
AnnaBridge | 172:7d866c31b3c5 | 298 | result = I2C_WRITE_ADDRESSED; |
AnnaBridge | 172:7d866c31b3c5 | 299 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 300 | result = I2C_READ_ADDRESSED; |
AnnaBridge | 172:7d866c31b3c5 | 301 | } |
AnnaBridge | 172:7d866c31b3c5 | 302 | } |
AnnaBridge | 172:7d866c31b3c5 | 303 | return (result); |
AnnaBridge | 172:7d866c31b3c5 | 304 | } |
AnnaBridge | 172:7d866c31b3c5 | 305 | |
AnnaBridge | 172:7d866c31b3c5 | 306 | int i2c_slave_read(i2c_t *obj, char *data, int length) |
AnnaBridge | 172:7d866c31b3c5 | 307 | { |
AnnaBridge | 172:7d866c31b3c5 | 308 | int32_t count = 0; |
AnnaBridge | 172:7d866c31b3c5 | 309 | |
AnnaBridge | 172:7d866c31b3c5 | 310 | while (count < length) { |
AnnaBridge | 172:7d866c31b3c5 | 311 | int32_t pdata = i2c_byte_read(obj, ((count < (length - 1))? 0: 1)); |
AnnaBridge | 172:7d866c31b3c5 | 312 | status = I2C_GetState(obj->i2c); |
AnnaBridge | 172:7d866c31b3c5 | 313 | if (status.Bit.TRx) { |
AnnaBridge | 172:7d866c31b3c5 | 314 | return (count); |
AnnaBridge | 172:7d866c31b3c5 | 315 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 316 | if (pdata < 0) { |
AnnaBridge | 172:7d866c31b3c5 | 317 | break; |
AnnaBridge | 172:7d866c31b3c5 | 318 | } |
AnnaBridge | 172:7d866c31b3c5 | 319 | data[count++] = (uint8_t)pdata; |
AnnaBridge | 172:7d866c31b3c5 | 320 | } |
AnnaBridge | 172:7d866c31b3c5 | 321 | } |
AnnaBridge | 172:7d866c31b3c5 | 322 | i2c_slave_mode(obj, 1); |
AnnaBridge | 172:7d866c31b3c5 | 323 | return (count); |
AnnaBridge | 172:7d866c31b3c5 | 324 | } |
AnnaBridge | 172:7d866c31b3c5 | 325 | |
AnnaBridge | 172:7d866c31b3c5 | 326 | int i2c_slave_write(i2c_t *obj, const char *data, int length) |
AnnaBridge | 172:7d866c31b3c5 | 327 | { |
AnnaBridge | 172:7d866c31b3c5 | 328 | int32_t count = 0; |
AnnaBridge | 172:7d866c31b3c5 | 329 | |
AnnaBridge | 172:7d866c31b3c5 | 330 | while (count < length) { |
AnnaBridge | 172:7d866c31b3c5 | 331 | if (i2c_byte_write(obj, (int32_t)data[count++]) < I2C_ACK) { |
AnnaBridge | 172:7d866c31b3c5 | 332 | break; |
AnnaBridge | 172:7d866c31b3c5 | 333 | } |
AnnaBridge | 172:7d866c31b3c5 | 334 | } |
AnnaBridge | 172:7d866c31b3c5 | 335 | i2c_slave_mode(obj, 1); |
AnnaBridge | 172:7d866c31b3c5 | 336 | return (count); |
AnnaBridge | 172:7d866c31b3c5 | 337 | } |
AnnaBridge | 172:7d866c31b3c5 | 338 | |
AnnaBridge | 172:7d866c31b3c5 | 339 | void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) |
AnnaBridge | 172:7d866c31b3c5 | 340 | { |
AnnaBridge | 172:7d866c31b3c5 | 341 | obj->address = address & 0xFE; |
AnnaBridge | 172:7d866c31b3c5 | 342 | i2c_slave_mode(obj, 1); |
AnnaBridge | 172:7d866c31b3c5 | 343 | } |